OpenTTD
company_gui.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of OpenTTD.
3  * 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.
4  * 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.
5  * 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/>.
6  */
7 
10 #include "stdafx.h"
11 #include "error.h"
12 #include "gui.h"
13 #include "window_gui.h"
14 #include "textbuf_gui.h"
15 #include "viewport_func.h"
16 #include "company_func.h"
17 #include "command_func.h"
18 #include "network/network.h"
19 #include "network/network_gui.h"
20 #include "network/network_func.h"
21 #include "newgrf.h"
22 #include "company_manager_face.h"
23 #include "strings_func.h"
24 #include "date_func.h"
25 #include "widgets/dropdown_type.h"
26 #include "tilehighlight_func.h"
27 #include "company_base.h"
28 #include "core/geometry_func.hpp"
29 #include "object_type.h"
30 #include "rail.h"
31 #include "road.h"
32 #include "engine_base.h"
33 #include "window_func.h"
34 #include "road_func.h"
35 #include "water.h"
36 #include "station_func.h"
37 #include "zoom_func.h"
38 #include "sortlist_type.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 
273  static Money max_money;
274  bool small;
275 
276  CompanyFinancesWindow(WindowDesc *desc, CompanyID company) : Window(desc)
277  {
278  this->small = false;
279  this->CreateNestedTree();
280  this->SetupWidgets();
281  this->FinishInitNested(company);
282 
283  this->owner = (Owner)this->window_number;
284  }
285 
286  void SetStringParameters(int widget) const override
287  {
288  switch (widget) {
289  case WID_CF_CAPTION:
290  SetDParam(0, (CompanyID)this->window_number);
291  SetDParam(1, (CompanyID)this->window_number);
292  break;
293 
295  SetDParam(0, _economy.max_loan);
296  break;
297 
299  case WID_CF_REPAY_LOAN:
301  break;
302  }
303  }
304 
305  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
306  {
308  switch (widget) {
310  size->width = _expenses_list_types[type].GetCategoriesWidth();
311  size->height = _expenses_list_types[type].GetHeight();
312  break;
313 
314  case WID_CF_EXPS_PRICE1:
315  case WID_CF_EXPS_PRICE2:
316  case WID_CF_EXPS_PRICE3:
317  size->height = _expenses_list_types[type].GetHeight();
318  FALLTHROUGH;
319 
321  case WID_CF_LOAN_VALUE:
322  case WID_CF_TOTAL_VALUE:
324  size->width = max(GetStringBoundingBox(STR_FINANCES_NEGATIVE_INCOME).width, GetStringBoundingBox(STR_FINANCES_POSITIVE_INCOME).width) + padding.width;
325  break;
326 
327  case WID_CF_MAXLOAN_GAP:
328  size->height = FONT_HEIGHT_NORMAL;
329  break;
330  }
331  }
332 
333  void DrawWidget(const Rect &r, int widget) const override
334  {
335  switch (widget) {
337  DrawCategories(r);
338  break;
339 
340  case WID_CF_EXPS_PRICE1:
341  case WID_CF_EXPS_PRICE2:
342  case WID_CF_EXPS_PRICE3: {
343  const Company *c = Company::Get((CompanyID)this->window_number);
344  int age = min(_cur_year - c->inaugurated_year, 2);
345  int wid_offset = widget - WID_CF_EXPS_PRICE1;
346  if (wid_offset <= age) {
347  DrawYearColumn(r, _cur_year - (age - wid_offset), c->yearly_expenses + (age - wid_offset));
348  }
349  break;
350  }
351 
352  case WID_CF_BALANCE_VALUE: {
353  const Company *c = Company::Get((CompanyID)this->window_number);
354  SetDParam(0, c->money);
355  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
356  break;
357  }
358 
359  case WID_CF_LOAN_VALUE: {
360  const Company *c = Company::Get((CompanyID)this->window_number);
361  SetDParam(0, c->current_loan);
362  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
363  break;
364  }
365 
366  case WID_CF_TOTAL_VALUE: {
367  const Company *c = Company::Get((CompanyID)this->window_number);
368  SetDParam(0, c->money - c->current_loan);
369  DrawString(r.left, r.right, r.top, STR_FINANCES_TOTAL_CURRENCY, TC_FROMSTRING, SA_RIGHT);
370  break;
371  }
372 
373  case WID_CF_LOAN_LINE:
374  GfxFillRect(r.left, r.top, r.right, r.top, PC_BLACK);
375  break;
376  }
377  }
378 
384  {
385  int plane = this->small ? SZSP_NONE : 0;
386  this->GetWidget<NWidgetStacked>(WID_CF_SEL_PANEL)->SetDisplayedPlane(plane);
387  this->GetWidget<NWidgetStacked>(WID_CF_SEL_MAXLOAN)->SetDisplayedPlane(plane);
388 
389  CompanyID company = (CompanyID)this->window_number;
390  plane = (company != _local_company) ? SZSP_NONE : 0;
391  this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->SetDisplayedPlane(plane);
392  }
393 
394  void OnPaint() override
395  {
396  if (!this->IsShaded()) {
397  if (!this->small) {
398  /* Check that the expenses panel height matches the height needed for the layout. */
400  if (_expenses_list_types[type].GetHeight() != this->GetWidget<NWidgetBase>(WID_CF_EXPS_CATEGORY)->current_y) {
401  this->SetupWidgets();
402  this->ReInit();
403  return;
404  }
405  }
406 
407  /* Check that the loan buttons are shown only when the user owns the company. */
408  CompanyID company = (CompanyID)this->window_number;
409  int req_plane = (company != _local_company) ? SZSP_NONE : 0;
410  if (req_plane != this->GetWidget<NWidgetStacked>(WID_CF_SEL_BUTTONS)->shown_plane) {
411  this->SetupWidgets();
412  this->ReInit();
413  return;
414  }
415 
416  const Company *c = Company::Get(company);
417  this->SetWidgetDisabledState(WID_CF_INCREASE_LOAN, c->current_loan == _economy.max_loan); // Borrow button only shows when there is any more money to loan.
418  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.
419  }
420 
421  this->DrawWidgets();
422  }
423 
424  void OnClick(Point pt, int widget, int click_count) override
425  {
426  switch (widget) {
427  case WID_CF_TOGGLE_SIZE: // toggle size
428  this->small = !this->small;
429  this->SetupWidgets();
430  if (this->IsShaded()) {
431  /* Finances window is not resizable, so size hints given during unshading have no effect
432  * on the changed appearance of the window. */
433  this->SetShaded(false);
434  } else {
435  this->ReInit();
436  }
437  break;
438 
439  case WID_CF_INCREASE_LOAN: // increase loan
440  DoCommandP(0, 0, _ctrl_pressed, CMD_INCREASE_LOAN | CMD_MSG(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY));
441  break;
442 
443  case WID_CF_REPAY_LOAN: // repay loan
444  DoCommandP(0, 0, _ctrl_pressed, CMD_DECREASE_LOAN | CMD_MSG(STR_ERROR_CAN_T_REPAY_LOAN));
445  break;
446 
447  case WID_CF_INFRASTRUCTURE: // show infrastructure details
448  ShowCompanyInfrastructure((CompanyID)this->window_number);
449  break;
450  }
451  }
452 
453  void OnHundredthTick() override
454  {
455  const Company *c = Company::Get((CompanyID)this->window_number);
458  this->SetupWidgets();
459  this->ReInit();
460  }
461  }
462 };
463 
466 
467 static WindowDesc _company_finances_desc(
468  WDP_AUTO, "company_finances", 0, 0,
470  0,
471  _nested_company_finances_widgets, lengthof(_nested_company_finances_widgets)
472 );
473 
480 {
481  if (!Company::IsValidID(company)) return;
482  if (BringWindowToFrontById(WC_FINANCES, company)) return;
483 
484  new CompanyFinancesWindow(&_company_finances_desc, company);
485 }
486 
487 /* List of colours for the livery window */
488 static const StringID _colour_dropdown[] = {
489  STR_COLOUR_DARK_BLUE,
490  STR_COLOUR_PALE_GREEN,
491  STR_COLOUR_PINK,
492  STR_COLOUR_YELLOW,
493  STR_COLOUR_RED,
494  STR_COLOUR_LIGHT_BLUE,
495  STR_COLOUR_GREEN,
496  STR_COLOUR_DARK_GREEN,
497  STR_COLOUR_BLUE,
498  STR_COLOUR_CREAM,
499  STR_COLOUR_MAUVE,
500  STR_COLOUR_PURPLE,
501  STR_COLOUR_ORANGE,
502  STR_COLOUR_BROWN,
503  STR_COLOUR_GREY,
504  STR_COLOUR_WHITE,
505 };
506 
507 /* Association of liveries to livery classes */
508 static const LiveryClass _livery_class[LS_END] = {
509  LC_OTHER,
510  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,
511  LC_ROAD, LC_ROAD,
512  LC_SHIP, LC_SHIP,
513  LC_AIRCRAFT, LC_AIRCRAFT, LC_AIRCRAFT,
514  LC_ROAD, LC_ROAD,
515 };
516 
518 public:
519  DropDownListColourItem(int result, bool masked) : DropDownListItem(result, masked) {}
520 
521  StringID String() const
522  {
523  return this->result >= COLOUR_END ? STR_COLOUR_DEFAULT : _colour_dropdown[this->result];
524  }
525 
526  uint Height(uint width) const override
527  {
528  return max(FONT_HEIGHT_NORMAL, ScaleGUITrad(12) + 2);
529  }
530 
531  bool Selectable() const override
532  {
533  return true;
534  }
535 
536  void Draw(int left, int right, int top, int bottom, bool sel, Colours bg_colour) const override
537  {
538  bool rtl = _current_text_dir == TD_RTL;
539  int height = bottom - top;
540  int icon_y_offset = height / 2;
541  int text_y_offset = (height - FONT_HEIGHT_NORMAL) / 2 + 1;
542  DrawSprite(SPR_VEH_BUS_SIDE_VIEW, PALETTE_RECOLOUR_START + (this->result % COLOUR_END),
543  rtl ? right - 2 - ScaleGUITrad(14) : left + ScaleGUITrad(14) + 2,
544  top + icon_y_offset);
545  DrawString(rtl ? left + 2 : left + ScaleGUITrad(28) + 4,
546  rtl ? right - ScaleGUITrad(28) - 4 : right - 2,
547  top + text_y_offset, this->String(), sel ? TC_WHITE : TC_BLACK);
548  }
549 };
550 
551 static const int LEVEL_WIDTH = 10;
552 
554 
557 private:
558  uint32 sel;
559  LiveryClass livery_class;
560  Dimension square;
561  uint rows;
562  uint line_height;
563  GUIGroupList groups;
564  std::vector<int> indents;
565  Scrollbar *vscroll;
566 
567  void ShowColourDropDownMenu(uint32 widget)
568  {
569  uint32 used_colours = 0;
570  const Company *c;
571  const Livery *livery, *default_livery = nullptr;
572  bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
573  byte default_col;
574 
575  /* Disallow other company colours for the primary colour */
576  if (this->livery_class < LC_GROUP_RAIL && HasBit(this->sel, LS_DEFAULT) && primary) {
577  for (const Company *c : Company::Iterate()) {
578  if (c->index != _local_company) SetBit(used_colours, c->colour);
579  }
580  }
581 
582  c = Company::Get((CompanyID)this->window_number);
583 
584  if (this->livery_class < LC_GROUP_RAIL) {
585  /* Get the first selected livery to use as the default dropdown item */
586  LiveryScheme scheme;
587  for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
588  if (HasBit(this->sel, scheme)) break;
589  }
590  if (scheme == LS_END) scheme = LS_DEFAULT;
591  livery = &c->livery[scheme];
592  if (scheme != LS_DEFAULT) default_livery = &c->livery[LS_DEFAULT];
593  } else {
594  const Group *g = Group::Get(this->sel);
595  livery = &g->livery;
596  if (g->parent == INVALID_GROUP) {
597  default_livery = &c->livery[LS_DEFAULT];
598  } else {
599  const Group *pg = Group::Get(g->parent);
600  default_livery = &pg->livery;
601  }
602  }
603 
604  DropDownList list;
605  if (default_livery != nullptr) {
606  /* Add COLOUR_END to put the colour out of range, but also allow us to show what the default is */
607  default_col = (primary ? default_livery->colour1 : default_livery->colour2) + COLOUR_END;
608  list.emplace_back(new DropDownListColourItem(default_col, false));
609  }
610  for (uint i = 0; i < lengthof(_colour_dropdown); i++) {
611  list.emplace_back(new DropDownListColourItem(i, HasBit(used_colours, i)));
612  }
613 
614  byte sel = (default_livery == nullptr || HasBit(livery->in_use, primary ? 0 : 1)) ? (primary ? livery->colour1 : livery->colour2) : default_col;
615  ShowDropDownList(this, std::move(list), sel, widget);
616  }
617 
618  static bool GroupNameSorter(const Group * const &a, const Group * const &b)
619  {
620  static const Group *last_group[2] = { nullptr, nullptr };
621  static char last_name[2][64] = { "", "" };
622 
623  if (a != last_group[0]) {
624  last_group[0] = a;
625  SetDParam(0, a->index);
626  GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
627  }
628 
629  if (b != last_group[1]) {
630  last_group[1] = b;
631  SetDParam(0, b->index);
632  GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
633  }
634 
635  int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
636  if (r == 0) return a->index < b->index;
637  return r < 0;
638  }
639 
640  void AddChildren(GUIGroupList *source, GroupID parent, int indent)
641  {
642  for (const Group *g : *source) {
643  if (g->parent != parent) continue;
644  this->groups.push_back(g);
645  this->indents.push_back(indent);
646  AddChildren(source, g->index, indent + 1);
647  }
648  }
649 
650  void BuildGroupList(CompanyID owner)
651  {
652  if (!this->groups.NeedRebuild()) return;
653 
654  this->groups.clear();
655  this->indents.clear();
656 
657  if (this->livery_class >= LC_GROUP_RAIL) {
658  GUIGroupList list;
659  VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
660 
661  for (const Group *g : Group::Iterate()) {
662  if (g->owner == owner && g->vehicle_type == vtype) {
663  list.push_back(g);
664  }
665  }
666 
667  list.ForceResort();
668  list.Sort(&GroupNameSorter);
669 
670  AddChildren(&list, INVALID_GROUP, 0);
671  }
672 
673  this->groups.shrink_to_fit();
674  this->groups.RebuildDone();
675  }
676 
677  void SetRows()
678  {
679  if (this->livery_class < LC_GROUP_RAIL) {
680  this->rows = 0;
681  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
682  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
683  this->rows++;
684  }
685  }
686  } else {
687  this->rows = (uint)this->groups.size();
688  }
689 
690  this->vscroll->SetCount(this->rows);
691  }
692 
693 public:
694  SelectCompanyLiveryWindow(WindowDesc *desc, CompanyID company, GroupID group) : Window(desc)
695  {
696  this->CreateNestedTree();
697  this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
698 
699  if (group == INVALID_GROUP) {
700  this->livery_class = LC_OTHER;
701  this->sel = 1;
702  this->LowerWidget(WID_SCL_CLASS_GENERAL);
703  this->BuildGroupList(company);
704  this->SetRows();
705  } else {
706  this->SetSelectedGroup(company, group);
707  }
708 
709  this->FinishInitNested(company);
710  this->owner = company;
711  this->InvalidateData(1);
712  }
713 
714  void SetSelectedGroup(CompanyID company, GroupID group)
715  {
716  this->RaiseWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
717  const Group *g = Group::Get(group);
718  switch (g->vehicle_type) {
719  case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
720  case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
721  case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
722  case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
723  default: NOT_REACHED();
724  }
725  this->sel = group;
726  this->LowerWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
727 
728  this->groups.ForceRebuild();
729  this->BuildGroupList(company);
730  this->SetRows();
731 
732  /* Position scrollbar to selected group */
733  for (uint i = 0; i < this->rows; i++) {
734  if (this->groups[i]->index == sel) {
735  this->vscroll->SetPosition(Clamp(i - this->vscroll->GetCapacity() / 2, 0, max(this->vscroll->GetCount() - this->vscroll->GetCapacity(), 0)));
736  break;
737  }
738  }
739  }
740 
741  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
742  {
743  switch (widget) {
745  /* The matrix widget below needs enough room to print all the schemes. */
746  Dimension d = {0, 0};
747  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
748  d = maxdim(d, GetStringBoundingBox(STR_LIVERY_DEFAULT + scheme));
749  }
750 
751  /* And group names */
752  for (const Group *g : Group::Iterate()) {
753  if (g->owner == (CompanyID)this->window_number) {
754  SetDParam(0, g->index);
755  d = maxdim(d, GetStringBoundingBox(STR_GROUP_NAME));
756  }
757  }
758 
759  size->width = max(size->width, 5 + d.width + WD_FRAMERECT_RIGHT);
760  break;
761  }
762 
763  case WID_SCL_MATRIX: {
764  /* 11 items in the default rail class */
765  this->square = GetSpriteSize(SPR_SQUARE);
766  this->line_height = max(this->square.height, (uint)FONT_HEIGHT_NORMAL) + 4;
767 
768  size->height = 11 * this->line_height;
769  resize->width = 1;
770  resize->height = this->line_height;
771  break;
772  }
773 
776  size->width = 0;
777  break;
778  }
779  FALLTHROUGH;
780 
782  this->square = GetSpriteSize(SPR_SQUARE);
783  int padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10;
784  for (const StringID *id = _colour_dropdown; id != endof(_colour_dropdown); id++) {
785  size->width = max(size->width, GetStringBoundingBox(*id).width + padding);
786  }
787  size->width = max(size->width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + padding);
788  break;
789  }
790  }
791  }
792 
793  void OnPaint() override
794  {
795  bool local = (CompanyID)this->window_number == _local_company;
796 
797  /* Disable dropdown controls if no scheme is selected */
798  bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == INVALID_GROUP);
799  this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
800  this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
801 
802  this->BuildGroupList((CompanyID)this->window_number);
803 
804  this->DrawWidgets();
805  }
806 
807  void SetStringParameters(int widget) const override
808  {
809  switch (widget) {
810  case WID_SCL_CAPTION:
811  SetDParam(0, (CompanyID)this->window_number);
812  break;
813 
816  const Company *c = Company::Get((CompanyID)this->window_number);
817  bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
818  StringID colour = STR_COLOUR_DEFAULT;
819 
820  if (this->livery_class < LC_GROUP_RAIL) {
821  if (this->sel != 0) {
822  LiveryScheme scheme = LS_DEFAULT;
823  for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
824  if (HasBit(this->sel, scheme)) break;
825  }
826  if (scheme == LS_END) scheme = LS_DEFAULT;
827  const Livery *livery = &c->livery[scheme];
828  if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
829  colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
830  }
831  }
832  } else {
833  if (this->sel != INVALID_GROUP) {
834  const Group *g = Group::Get(this->sel);
835  const Livery *livery = &g->livery;
836  if (HasBit(livery->in_use, primary ? 0 : 1)) {
837  colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
838  }
839  }
840  }
841  SetDParam(0, colour);
842  break;
843  }
844  }
845  }
846 
847  void DrawWidget(const Rect &r, int widget) const override
848  {
849  if (widget != WID_SCL_MATRIX) return;
850 
851  bool rtl = _current_text_dir == TD_RTL;
852 
853  /* Horizontal coordinates of scheme name column. */
854  const NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SCL_SPACER_DROPDOWN);
855  int sch_left = nwi->pos_x;
856  int sch_right = sch_left + nwi->current_x - 1;
857  /* Horizontal coordinates of first dropdown. */
858  nwi = this->GetWidget<NWidgetBase>(WID_SCL_PRI_COL_DROPDOWN);
859  int pri_left = nwi->pos_x;
860  int pri_right = pri_left + nwi->current_x - 1;
861  /* Horizontal coordinates of second dropdown. */
862  nwi = this->GetWidget<NWidgetBase>(WID_SCL_SEC_COL_DROPDOWN);
863  int sec_left = nwi->pos_x;
864  int sec_right = sec_left + nwi->current_x - 1;
865 
866  int text_left = (rtl ? (uint)WD_FRAMERECT_LEFT : (this->square.width + 5));
867  int text_right = (rtl ? (this->square.width + 5) : (uint)WD_FRAMERECT_RIGHT);
868 
869  int square_offs = (this->line_height - this->square.height) / 2 + 1;
870  int text_offs = (this->line_height - FONT_HEIGHT_NORMAL) / 2 + 1;
871 
872  int y = r.top;
873 
874  /* Helper function to draw livery info. */
875  auto draw_livery = [&](StringID str, const Livery &liv, bool sel, bool def, int indent) {
876  /* Livery Label. */
877  DrawString(sch_left + WD_FRAMERECT_LEFT + (rtl ? 0 : indent), sch_right - WD_FRAMERECT_RIGHT - (rtl ? indent : 0), y + text_offs, str, sel ? TC_WHITE : TC_BLACK);
878 
879  /* Text below the first dropdown. */
880  DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour1), (rtl ? pri_right - (this->square.width + 5) + WD_FRAMERECT_RIGHT : pri_left) + WD_FRAMERECT_LEFT, y + square_offs);
881  DrawString(pri_left + text_left, pri_right - text_right, y + text_offs, (def || HasBit(liv.in_use, 0)) ? STR_COLOUR_DARK_BLUE + liv.colour1 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD);
882 
883  /* Text below the second dropdown. */
884  if (sec_right > sec_left) { // Second dropdown has non-zero size.
885  DrawSprite(SPR_SQUARE, GENERAL_SPRITE_COLOUR(liv.colour2), (rtl ? sec_right - (this->square.width + 5) + WD_FRAMERECT_RIGHT : sec_left) + WD_FRAMERECT_LEFT, y + square_offs);
886  DrawString(sec_left + text_left, sec_right - text_right, y + text_offs, (def || HasBit(liv.in_use, 1)) ? STR_COLOUR_DARK_BLUE + liv.colour2 : STR_COLOUR_DEFAULT, sel ? TC_WHITE : TC_GOLD);
887  }
888 
889  y += this->line_height;
890  };
891 
892  if (livery_class < LC_GROUP_RAIL) {
893  int pos = this->vscroll->GetPosition();
894  const Company *c = Company::Get((CompanyID)this->window_number);
895  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
896  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
897  if (pos-- > 0) continue;
898  draw_livery(STR_LIVERY_DEFAULT + scheme, c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
899  }
900  }
901  } else {
902  uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (uint)this->groups.size());
903  for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
904  const Group *g = this->groups[i];
905  SetDParam(0, g->index);
906  draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * LEVEL_WIDTH);
907  }
908  }
909  }
910 
911  void OnClick(Point pt, int widget, int click_count) override
912  {
913  switch (widget) {
914  /* Livery Class buttons */
916  case WID_SCL_CLASS_RAIL:
917  case WID_SCL_CLASS_ROAD:
918  case WID_SCL_CLASS_SHIP:
920  case WID_SCL_GROUPS_RAIL:
921  case WID_SCL_GROUPS_ROAD:
922  case WID_SCL_GROUPS_SHIP:
924  this->RaiseWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
925  this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
926  this->LowerWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
927 
928  /* Select the first item in the list */
929  if (this->livery_class < LC_GROUP_RAIL) {
930  this->sel = 0;
931  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
932  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
933  this->sel = 1 << scheme;
934  break;
935  }
936  }
937  } else {
938  this->sel = INVALID_GROUP;
939  this->groups.ForceRebuild();
940  this->BuildGroupList((CompanyID)this->window_number);
941 
942  if (this->groups.size() > 0) {
943  this->sel = this->groups[0]->index;
944  }
945  }
946 
947  this->SetRows();
948  this->SetDirty();
949  break;
950 
951  case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
952  ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
953  break;
954 
955  case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
956  ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
957  break;
958 
959  case WID_SCL_MATRIX: {
960  uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCL_MATRIX, 0, this->line_height);
961  if (row >= this->rows) return;
962 
963  if (this->livery_class < LC_GROUP_RAIL) {
964  LiveryScheme j = (LiveryScheme)row;
965 
966  for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
967  if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
968  }
969  assert(j < LS_END);
970 
971  if (_ctrl_pressed) {
972  ToggleBit(this->sel, j);
973  } else {
974  this->sel = 1 << j;
975  }
976  } else {
977  this->sel = this->groups[row]->index;
978  }
979  this->SetDirty();
980  break;
981  }
982  }
983  }
984 
985  void OnResize() override
986  {
987  this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
988  }
989 
990  void OnDropdownSelect(int widget, int index) override
991  {
992  bool local = (CompanyID)this->window_number == _local_company;
993  if (!local) return;
994 
995  if (index >= COLOUR_END) index = INVALID_COLOUR;
996 
997  if (this->livery_class < LC_GROUP_RAIL) {
998  /* Set company colour livery */
999  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1000  /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
1001  if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1002  DoCommandP(0, scheme | (widget == WID_SCL_PRI_COL_DROPDOWN ? 0 : 256), index, CMD_SET_COMPANY_COLOUR);
1003  }
1004  }
1005  } else {
1006  /* Setting group livery */
1007  DoCommandP(0, this->sel, (widget == WID_SCL_PRI_COL_DROPDOWN ? 0 : 256) | (index << 16), CMD_SET_GROUP_LIVERY);
1008  }
1009  }
1010 
1016  void OnInvalidateData(int data = 0, bool gui_scope = true) override
1017  {
1018  if (!gui_scope) return;
1019 
1020  if (data != -1) {
1021  /* data contains a VehicleType, rebuild list if it displayed */
1022  if (this->livery_class == data + LC_GROUP_RAIL) {
1023  this->groups.ForceRebuild();
1024  this->BuildGroupList((CompanyID)this->window_number);
1025  this->SetRows();
1026 
1027  if (!Group::IsValidID(this->sel)) {
1028  this->sel = INVALID_GROUP;
1029  if (this->groups.size() > 0) this->sel = this->groups[0]->index;
1030  }
1031 
1032  this->SetDirty();
1033  }
1034  return;
1035  }
1036 
1038 
1039  bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1040  if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
1041  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1043  if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1044  this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1045  } else if (this->livery_class < LC_GROUP_RAIL) {
1046  ClrBit(this->sel, scheme);
1047  }
1048  }
1049  }
1050 
1051  if (!current_class_valid) {
1052  Point pt = {0, 0};
1053  this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1054  }
1055  }
1056 };
1057 
1058 static const NWidgetPart _nested_select_company_livery_widgets [] = {
1060  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1061  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1062  EndContainer(),
1064  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1065  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1066  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1067  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1068  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1069  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_TOOLTIP),
1070  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_ROADVEH, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1071  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_TOOLTIP),
1072  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_TOOLTIP),
1073  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(),
1074  EndContainer(),
1076  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(),
1077  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_BLACK_STRING, STR_LIVERY_PRIMARY_TOOLTIP),
1078  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1),
1079  SetDataTip(STR_BLACK_STRING, STR_LIVERY_SECONDARY_TOOLTIP),
1080  EndContainer(),
1082  NWidget(WWT_MATRIX, COLOUR_GREY, WID_SCL_MATRIX), SetMinimalSize(275, 0), SetResize(1, 0), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_LIVERY_PANEL_TOOLTIP), SetScrollbar(WID_SCL_MATRIX_SCROLLBAR),
1085  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1086  EndContainer(),
1087  EndContainer(),
1088 };
1089 
1090 static WindowDesc _select_company_livery_desc(
1091  WDP_AUTO, "company_livery", 0, 0,
1093  0,
1094  _nested_select_company_livery_widgets, lengthof(_nested_select_company_livery_widgets)
1095 );
1096 
1097 void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1098 {
1100  if (w == nullptr) {
1101  new SelectCompanyLiveryWindow(&_select_company_livery_desc, company, group);
1102  } else if (group != INVALID_GROUP) {
1103  w->SetSelectedGroup(company, group);
1104  }
1105 }
1106 
1114 void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
1115 {
1117 
1118  bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1119  bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1120  bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1121  PaletteID pal;
1122 
1123  /* Modify eye colour palette only if 2 or more valid values exist */
1124  if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1125  pal = PAL_NONE;
1126  } else {
1127  switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1128  default: NOT_REACHED();
1129  case 0: pal = PALETTE_TO_BROWN; break;
1130  case 1: pal = PALETTE_TO_BLUE; break;
1131  case 2: pal = PALETTE_TO_GREEN; break;
1132  }
1133  }
1134 
1135  /* Draw the gradient (background) */
1136  DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1137 
1138  for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1139  switch (cmfv) {
1140  case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1141  case CMFV_LIPS:
1142  case CMFV_NOSE: if (has_moustache) continue; break;
1143  case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1144  case CMFV_GLASSES: if (!has_glasses) continue; break;
1145  default: break;
1146  }
1147  DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1148  }
1149 }
1150 
1154  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1155  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1156  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP),
1157  EndContainer(),
1158  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1160  NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
1163  NWidget(NWID_SPACER), SetFill(1, 0),
1164  NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCMF_FACE), SetMinimalSize(92, 119),
1165  NWidget(NWID_SPACER), SetFill(1, 0),
1166  EndContainer(),
1168  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetDataTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1169  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1171  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1172  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetDataTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1173  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetDataTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1174  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetDataTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1175  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1176  EndContainer(),
1177  EndContainer(),
1178  EndContainer(),
1180  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1182  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1184  NWidget(NWID_SPACER), SetFill(0, 1),
1185  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1186  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1187  NWidget(NWID_SPACER), SetFill(0, 1),
1188  EndContainer(),
1189  EndContainer(),
1190  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1194  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1195  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1196  EndContainer(),
1199  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
1200  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
1201  EndContainer(),
1205  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
1206  EndContainer(),
1208  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1209  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
1210  EndContainer(),
1211  NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
1213  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1214  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1215  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
1216  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1217  EndContainer(),
1219  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1220  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1221  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
1222  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1223  EndContainer(),
1225  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1226  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1227  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
1228  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1229  EndContainer(),
1231  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1232  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1233  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
1234  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1235  EndContainer(),
1237  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1238  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1239  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
1240  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1241  EndContainer(),
1243  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1244  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1245  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1246  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1247  EndContainer(),
1249  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1250  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1251  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
1252  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1253  EndContainer(),
1255  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1256  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1257  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
1258  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1259  EndContainer(),
1261  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1262  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1263  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
1264  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1265  EndContainer(),
1267  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1268  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1269  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
1270  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1271  EndContainer(),
1272  NWidget(NWID_SPACER), SetFill(0, 1),
1273  EndContainer(),
1274  EndContainer(),
1275  EndContainer(),
1276  EndContainer(),
1278  EndContainer(),
1280  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1281  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1282  EndContainer(),
1283 };
1284 
1287 {
1289  bool advanced;
1290 
1292  bool is_female;
1294 
1297 
1298  static const StringID PART_TEXTS_IS_FEMALE[];
1299  static const StringID PART_TEXTS[];
1300 
1308  void DrawFaceStringLabel(byte widget_index, uint8 val, bool is_bool_widget) const
1309  {
1310  StringID str;
1311  const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1312  if (!nwi_widget->IsDisabled()) {
1313  if (is_bool_widget) {
1314  /* if it a bool button write yes or no */
1315  str = (val != 0) ? STR_FACE_YES : STR_FACE_NO;
1316  } else {
1317  /* else write the value + 1 */
1318  SetDParam(0, val + 1);
1319  str = STR_JUST_INT;
1320  }
1321 
1322  /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
1323  DrawString(nwi_widget->pos_x + nwi_widget->IsLowered(), nwi_widget->pos_x + nwi_widget->current_x - 1 - nwi_widget->IsLowered(),
1324  nwi_widget->pos_y + 1 + nwi_widget->IsLowered(), str, TC_WHITE, SA_HOR_CENTER);
1325  }
1326  }
1327 
1328  void UpdateData()
1329  {
1330  this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1331  this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1332  this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1333  }
1334 
1335 public:
1336  SelectCompanyManagerFaceWindow(WindowDesc *desc, Window *parent) : Window(desc)
1337  {
1338  this->advanced = false;
1339  this->CreateNestedTree();
1340  this->SelectDisplayPlanes(this->advanced);
1341  this->FinishInitNested(parent->window_number);
1342  this->parent = parent;
1343  this->owner = (Owner)this->window_number;
1344  this->face = Company::Get((CompanyID)this->window_number)->face;
1345 
1346  this->UpdateData();
1347  }
1348 
1353  void SelectDisplayPlanes(bool advanced)
1354  {
1355  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1356  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1357  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1358  this->GetWidget<NWidgetCore>(WID_SCMF_RANDOM_NEW_FACE)->widget_data = advanced ? STR_FACE_RANDOM : STR_FACE_NEW_FACE_BUTTON;
1359 
1360  NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1361  if (advanced) {
1362  wi->SetDataTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1363  } else {
1364  wi->SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1365  }
1366  }
1367 
1368  void OnInit() override
1369  {
1370  /* Size of the boolean yes/no button. */
1371  Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
1372  yesno_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1373  yesno_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1374  /* Size of the number button + arrows. */
1375  Dimension number_dim = {0, 0};
1376  for (int val = 1; val <= 12; val++) {
1377  SetDParam(0, val);
1378  number_dim = maxdim(number_dim, GetStringBoundingBox(STR_JUST_INT));
1379  }
1380  uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT);
1381  number_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + arrows_width;
1382  number_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1383  /* Compute width of both buttons. */
1384  yesno_dim.width = max(yesno_dim.width, number_dim.width);
1385  number_dim.width = yesno_dim.width - arrows_width;
1386 
1387  this->yesno_dim = yesno_dim;
1388  this->number_dim = number_dim;
1389  }
1390 
1391  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1392  {
1393  switch (widget) {
1394  case WID_SCMF_FACE: {
1395  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
1396  size->width = max(size->width, face_size.width);
1397  size->height = max(size->height, face_size.height);
1398  break;
1399  }
1400 
1403  int offset = (widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2;
1404  *size = maxdim(GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset]), GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset + 1]));
1405  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1406  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1407  break;
1408  }
1409 
1411  *size = maxdim(GetStringBoundingBox(STR_FACE_LIPS), GetStringBoundingBox(STR_FACE_MOUSTACHE));
1412  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1413  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1414  break;
1415 
1417  case WID_SCMF_HAIR_TEXT:
1420  case WID_SCMF_GLASSES_TEXT:
1421  case WID_SCMF_NOSE_TEXT:
1422  case WID_SCMF_CHIN_TEXT:
1423  case WID_SCMF_JACKET_TEXT:
1424  case WID_SCMF_COLLAR_TEXT:
1425  *size = GetStringBoundingBox(PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT]);
1426  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1427  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1428  break;
1429 
1431  case WID_SCMF_HAS_GLASSES:
1432  *size = this->yesno_dim;
1433  break;
1434 
1435  case WID_SCMF_EYECOLOUR:
1436  case WID_SCMF_CHIN:
1437  case WID_SCMF_EYEBROWS:
1439  case WID_SCMF_NOSE:
1440  case WID_SCMF_HAIR:
1441  case WID_SCMF_JACKET:
1442  case WID_SCMF_COLLAR:
1443  case WID_SCMF_TIE_EARRING:
1444  case WID_SCMF_GLASSES:
1445  *size = this->number_dim;
1446  break;
1447  }
1448  }
1449 
1450  void OnPaint() override
1451  {
1452  /* lower the non-selected gender button */
1453  this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2, WIDGET_LIST_END);
1454  this->SetWidgetsLoweredState( this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2, WIDGET_LIST_END);
1455 
1456  /* advanced company manager face selection window */
1457 
1458  /* lower the non-selected ethnicity button */
1459  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
1460  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
1461 
1462 
1463  /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1464  * (or in other words you haven't any choice).
1465  * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1466 
1467  /* Eye colour buttons */
1468  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1470 
1471  /* Chin buttons */
1472  this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1474 
1475  /* Eyebrows buttons */
1476  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1478 
1479  /* Lips or (if it a male face with a moustache) moustache buttons */
1480  this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1482 
1483  /* Nose buttons | male faces with moustache haven't any nose options */
1484  this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1486 
1487  /* Hair buttons */
1488  this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1490 
1491  /* Jacket buttons */
1492  this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1494 
1495  /* Collar buttons */
1496  this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1498 
1499  /* Tie/earring buttons | female faces without earring haven't any earring options */
1500  this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1501  (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1503 
1504  /* Glasses buttons | faces without glasses haven't any glasses options */
1505  this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1507 
1508  this->DrawWidgets();
1509  }
1510 
1511  void DrawWidget(const Rect &r, int widget) const override
1512  {
1513  switch (widget) {
1516  StringID str = PART_TEXTS_IS_FEMALE[(widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2 + this->is_female];
1517  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_GOLD, SA_RIGHT);
1518  break;
1519  }
1520 
1522  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);
1523  break;
1524 
1526  case WID_SCMF_HAIR_TEXT:
1529  case WID_SCMF_GLASSES_TEXT:
1530  case WID_SCMF_NOSE_TEXT:
1531  case WID_SCMF_CHIN_TEXT:
1532  case WID_SCMF_JACKET_TEXT:
1533  case WID_SCMF_COLLAR_TEXT:
1534  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);
1535  break;
1536 
1537 
1539  if (this->is_female) { // Only for female faces
1540  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true);
1541  } else { // Only for male faces
1542  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge), true);
1543  }
1544  break;
1545 
1546  case WID_SCMF_TIE_EARRING:
1547  this->DrawFaceStringLabel(WID_SCMF_TIE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1548  break;
1549 
1551  if (this->is_moust_male) { // Only for male faces with moustache
1552  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_MOUSTACHE, this->ge), false);
1553  } else { // Only for female faces or male faces without moustache
1554  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_LIPS, this->ge), false);
1555  }
1556  break;
1557 
1558  case WID_SCMF_HAS_GLASSES:
1559  this->DrawFaceStringLabel(WID_SCMF_HAS_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1560  break;
1561 
1562  case WID_SCMF_HAIR:
1563  this->DrawFaceStringLabel(WID_SCMF_HAIR, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1564  break;
1565 
1566  case WID_SCMF_EYEBROWS:
1567  this->DrawFaceStringLabel(WID_SCMF_EYEBROWS, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1568  break;
1569 
1570  case WID_SCMF_EYECOLOUR:
1571  this->DrawFaceStringLabel(WID_SCMF_EYECOLOUR, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1572  break;
1573 
1574  case WID_SCMF_GLASSES:
1575  this->DrawFaceStringLabel(WID_SCMF_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1576  break;
1577 
1578  case WID_SCMF_NOSE:
1579  this->DrawFaceStringLabel(WID_SCMF_NOSE, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1580  break;
1581 
1582  case WID_SCMF_CHIN:
1583  this->DrawFaceStringLabel(WID_SCMF_CHIN, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1584  break;
1585 
1586  case WID_SCMF_JACKET:
1587  this->DrawFaceStringLabel(WID_SCMF_JACKET, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1588  break;
1589 
1590  case WID_SCMF_COLLAR:
1591  this->DrawFaceStringLabel(WID_SCMF_COLLAR, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1592  break;
1593 
1594  case WID_SCMF_FACE:
1595  DrawCompanyManagerFace(this->face, Company::Get((CompanyID)this->window_number)->colour, r.left, r.top);
1596  break;
1597  }
1598  }
1599 
1600  void OnClick(Point pt, int widget, int click_count) override
1601  {
1602  switch (widget) {
1603  /* Toggle size, advanced/simple face selection */
1606  this->advanced = !this->advanced;
1607  this->SelectDisplayPlanes(this->advanced);
1608  this->ReInit();
1609  break;
1610 
1611  /* OK button */
1612  case WID_SCMF_ACCEPT:
1613  DoCommandP(0, 0, this->face, CMD_SET_COMPANY_MANAGER_FACE);
1614  FALLTHROUGH;
1615 
1616  /* Cancel button */
1617  case WID_SCMF_CANCEL:
1618  delete this;
1619  break;
1620 
1621  /* Load button */
1622  case WID_SCMF_LOAD:
1623  this->face = _company_manager_face;
1624  ScaleAllCompanyManagerFaceBits(this->face);
1625  ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, WL_INFO);
1626  this->UpdateData();
1627  this->SetDirty();
1628  break;
1629 
1630  /* 'Company manager face number' button, view and/or set company manager face number */
1631  case WID_SCMF_FACECODE:
1632  SetDParam(0, this->face);
1633  ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, this, CS_NUMERAL, QSF_NONE);
1634  break;
1635 
1636  /* Save button */
1637  case WID_SCMF_SAVE:
1638  _company_manager_face = this->face;
1639  ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, WL_INFO);
1640  break;
1641 
1642  /* Toggle gender (male/female) button */
1643  case WID_SCMF_MALE:
1644  case WID_SCMF_FEMALE:
1645  case WID_SCMF_MALE2:
1646  case WID_SCMF_FEMALE2:
1647  SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1648  ScaleAllCompanyManagerFaceBits(this->face);
1649  this->UpdateData();
1650  this->SetDirty();
1651  break;
1652 
1653  /* Randomize face button */
1655  RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced);
1656  this->UpdateData();
1657  this->SetDirty();
1658  break;
1659 
1660  /* Toggle ethnicity (european/african) button */
1663  SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1664  ScaleAllCompanyManagerFaceBits(this->face);
1665  this->UpdateData();
1666  this->SetDirty();
1667  break;
1668 
1669  default:
1670  /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1671  * First it checks which CompanyManagerFaceVariable is being changed, and then either
1672  * a: invert the value for boolean variables, or
1673  * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1674  if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1675  CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1676 
1677  if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1678  switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1679  default: NOT_REACHED();
1680  case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1681  case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1682  }
1683  SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1684  ScaleAllCompanyManagerFaceBits(this->face);
1685  } else { // Value buttons
1686  switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1687  default: NOT_REACHED();
1688  case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1689  case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1690  case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1691  case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1692  case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1693  case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1694  case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1695  case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1696  case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1697  case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1698  }
1699  /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1700  IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1701  }
1702  this->UpdateData();
1703  this->SetDirty();
1704  }
1705  break;
1706  }
1707  }
1708 
1709  void OnQueryTextFinished(char *str) override
1710  {
1711  if (str == nullptr) return;
1712  /* Set a new company manager face number */
1713  if (!StrEmpty(str)) {
1714  this->face = strtoul(str, nullptr, 10);
1715  ScaleAllCompanyManagerFaceBits(this->face);
1716  ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, WL_INFO);
1717  this->UpdateData();
1718  this->SetDirty();
1719  } else {
1720  ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, WL_INFO);
1721  }
1722  }
1723 };
1724 
1727  STR_FACE_MOUSTACHE, STR_FACE_EARRING, // WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
1728  STR_FACE_TIE, STR_FACE_EARRING, // WID_SCMF_TIE_EARRING_TEXT
1729 };
1730 
1733  STR_FACE_GLASSES, // WID_SCMF_HAS_GLASSES_TEXT
1734  STR_FACE_HAIR, // WID_SCMF_HAIR_TEXT
1735  STR_FACE_EYEBROWS, // WID_SCMF_EYEBROWS_TEXT
1736  STR_FACE_EYECOLOUR, // WID_SCMF_EYECOLOUR_TEXT
1737  STR_FACE_GLASSES, // WID_SCMF_GLASSES_TEXT
1738  STR_FACE_NOSE, // WID_SCMF_NOSE_TEXT
1739  STR_FACE_CHIN, // WID_SCMF_CHIN_TEXT
1740  STR_FACE_JACKET, // WID_SCMF_JACKET_TEXT
1741  STR_FACE_COLLAR, // WID_SCMF_COLLAR_TEXT
1742 };
1743 
1746  WDP_AUTO, "company_face", 0, 0,
1749  _nested_select_company_manager_face_widgets, lengthof(_nested_select_company_manager_face_widgets)
1750 );
1751 
1758 {
1759  if (!Company::IsValidID((CompanyID)parent->window_number)) return;
1760 
1762  new SelectCompanyManagerFaceWindow(&_select_company_manager_face_desc, parent);
1763 }
1764 
1765 static const NWidgetPart _nested_company_infrastructure_widgets[] = {
1767  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1768  NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), SetDataTip(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1769  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1770  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1771  EndContainer(),
1772  NWidget(WWT_PANEL, COLOUR_GREY),
1774  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1775  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1776  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1777  EndContainer(),
1778  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1779  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1780  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1781  EndContainer(),
1782  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1783  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1784  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1785  EndContainer(),
1786  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1787  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1788  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1789  EndContainer(),
1790  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1791  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1792  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1793  EndContainer(),
1794  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1795  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
1796  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
1797  EndContainer(),
1798  EndContainer(),
1799  EndContainer(),
1800 };
1801 
1806 {
1809 
1811 
1812  CompanyInfrastructureWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
1813  {
1814  this->UpdateRailRoadTypes();
1815 
1816  this->InitNested(window_number);
1817  this->owner = (Owner)this->window_number;
1818  }
1819 
1820  void UpdateRailRoadTypes()
1821  {
1822  this->railtypes = RAILTYPES_NONE;
1823  this->roadtypes = ROADTYPES_NONE;
1824 
1825  /* Find the used railtypes. */
1826  for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
1827  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1828 
1829  this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1830  }
1831 
1832  /* Get the date introduced railtypes as well. */
1833  this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY);
1834 
1835  /* Find the used roadtypes. */
1836  for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
1837  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1838 
1839  this->roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
1840  }
1841 
1842  /* Get the date introduced roadtypes as well. */
1843  this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DAY);
1844  this->roadtypes &= ~_roadtypes_hidden_mask;
1845  }
1846 
1849  {
1850  const Company *c = Company::Get((CompanyID)this->window_number);
1851  Money total;
1852 
1853  uint32 rail_total = c->infrastructure.GetRailTotal();
1854  for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1855  if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1856  }
1858 
1859  uint32 road_total = c->infrastructure.GetRoadTotal();
1860  uint32 tram_total = c->infrastructure.GetTramTotal();
1861  for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1862  if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
1863  }
1864 
1867  total += AirportMaintenanceCost(c->index);
1868 
1869  return total;
1870  }
1871 
1872  void SetStringParameters(int widget) const override
1873  {
1874  switch (widget) {
1875  case WID_CI_CAPTION:
1876  SetDParam(0, (CompanyID)this->window_number);
1877  break;
1878  }
1879  }
1880 
1881  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1882  {
1883  const Company *c = Company::Get((CompanyID)this->window_number);
1884 
1885  switch (widget) {
1886  case WID_CI_RAIL_DESC: {
1887  uint lines = 1;
1888 
1889  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width);
1890 
1891  RailType rt;
1893  if (HasBit(this->railtypes, rt)) {
1894  lines++;
1895  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
1896  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1897  }
1898  }
1899  if (this->railtypes != RAILTYPES_NONE) {
1900  lines++;
1901  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + WD_FRAMERECT_LEFT);
1902  }
1903 
1904  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1905  break;
1906  }
1907 
1908  case WID_CI_ROAD_DESC:
1909  case WID_CI_TRAM_DESC: {
1910  uint lines = 0;
1911 
1912  size->width = max(size->width, GetStringBoundingBox(widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT).width);
1913 
1914  RoadType rt;
1916  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
1917  lines++;
1918  SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
1919  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1920  }
1921  }
1922 
1923  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1924  break;
1925  }
1926 
1927  case WID_CI_WATER_DESC:
1928  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width);
1929  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + WD_FRAMERECT_LEFT);
1930  break;
1931 
1932  case WID_CI_STATION_DESC:
1933  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width);
1934  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + WD_FRAMERECT_LEFT);
1935  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + WD_FRAMERECT_LEFT);
1936  break;
1937 
1938  case WID_CI_RAIL_COUNT:
1939  case WID_CI_ROAD_COUNT:
1940  case WID_CI_TRAM_COUNT:
1941  case WID_CI_WATER_COUNT:
1942  case WID_CI_STATION_COUNT:
1943  case WID_CI_TOTAL: {
1944  /* Find the maximum count that is displayed. */
1945  uint32 max_val = 1000; // Some random number to reserve enough space.
1946  Money max_cost = 10000; // Some random number to reserve enough space.
1947  uint32 rail_total = c->infrastructure.GetRailTotal();
1948  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1949  max_val = max(max_val, c->infrastructure.rail[rt]);
1950  max_cost = max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1951  }
1952  max_val = max(max_val, c->infrastructure.signal);
1953  max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1954  uint32 road_total = c->infrastructure.GetRoadTotal();
1955  uint32 tram_total = c->infrastructure.GetTramTotal();
1956  for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1957  max_val = max(max_val, c->infrastructure.road[rt]);
1958  max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
1959 
1960  }
1961  max_val = max(max_val, c->infrastructure.water);
1962  max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1963  max_val = max(max_val, c->infrastructure.station);
1964  max_cost = max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1965  max_val = max(max_val, c->infrastructure.airport);
1966  max_cost = max(max_cost, AirportMaintenanceCost(c->index));
1967 
1968  SetDParamMaxValue(0, max_val);
1969  uint count_width = GetStringBoundingBox(STR_WHITE_COMMA).width + 20; // Reserve some wiggle room
1970 
1972  SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1973  this->total_width = GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width + 20;
1974  size->width = max(size->width, this->total_width);
1975 
1976  SetDParamMaxValue(0, max_cost * 12); // Convert to per year
1977  count_width += max(this->total_width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width);
1978  }
1979 
1980  size->width = max(size->width, count_width);
1981 
1982  /* Set height of the total line. */
1983  if (widget == WID_CI_TOTAL) {
1985  }
1986  break;
1987  }
1988  }
1989  }
1990 
1998  void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1999  {
2000  SetDParam(0, count);
2001  DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA, TC_FROMSTRING, SA_RIGHT);
2002 
2004  SetDParam(0, monthly_cost * 12); // Convert to per year
2005  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
2006  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
2007  }
2008  }
2009 
2010  void DrawWidget(const Rect &r, int widget) const override
2011  {
2012  const Company *c = Company::Get((CompanyID)this->window_number);
2013  int y = r.top;
2014 
2015  int offs_left = _current_text_dir == TD_LTR ? WD_FRAMERECT_LEFT : 0;
2016  int offs_right = _current_text_dir == TD_LTR ? 0 : WD_FRAMERECT_LEFT;
2017 
2018  switch (widget) {
2019  case WID_CI_RAIL_DESC:
2020  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
2021 
2022  if (this->railtypes != RAILTYPES_NONE) {
2023  /* Draw name of each valid railtype. */
2024  RailType rt;
2026  if (HasBit(this->railtypes, rt)) {
2027  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
2028  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
2029  }
2030  }
2031  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
2032  } else {
2033  /* No valid railtype. */
2034  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2035  }
2036 
2037  break;
2038 
2039  case WID_CI_RAIL_COUNT: {
2040  /* Draw infrastructure count for each valid railtype. */
2041  uint32 rail_total = c->infrastructure.GetRailTotal();
2042  RailType rt;
2044  if (HasBit(this->railtypes, rt)) {
2045  this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
2046  }
2047  }
2048  if (this->railtypes != RAILTYPES_NONE) {
2049  this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
2050  }
2051  break;
2052  }
2053 
2054  case WID_CI_ROAD_DESC:
2055  case WID_CI_TRAM_DESC: {
2056  DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
2057 
2058  /* Draw name of each valid roadtype. */
2059  RoadType rt;
2061  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
2062  SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
2063  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
2064  }
2065  }
2066 
2067  break;
2068  }
2069 
2070  case WID_CI_ROAD_COUNT:
2071  case WID_CI_TRAM_COUNT: {
2072  uint32 road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal();
2073  RoadType rt;
2075  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
2076  this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total));
2077  }
2078  }
2079  break;
2080  }
2081 
2082  case WID_CI_WATER_DESC:
2083  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
2084  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
2085  break;
2086 
2087  case WID_CI_WATER_COUNT:
2088  this->DrawCountLine(r, y, c->infrastructure.water, CanalMaintenanceCost(c->infrastructure.water));
2089  break;
2090 
2091  case WID_CI_TOTAL:
2093  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
2094  GfxFillRect(left, y, left + this->total_width, y, PC_WHITE);
2095  y += EXP_LINESPACE;
2096  SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
2097  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
2098  }
2099  break;
2100 
2101  case WID_CI_STATION_DESC:
2102  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
2103  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
2104  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
2105  break;
2106 
2107  case WID_CI_STATION_COUNT:
2108  this->DrawCountLine(r, y, c->infrastructure.station, StationMaintenanceCost(c->infrastructure.station));
2109  this->DrawCountLine(r, y, c->infrastructure.airport, AirportMaintenanceCost(c->index));
2110  break;
2111  }
2112  }
2113 
2119  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2120  {
2121  if (!gui_scope) return;
2122 
2123  this->UpdateRailRoadTypes();
2124  this->ReInit();
2125  }
2126 };
2127 
2128 static WindowDesc _company_infrastructure_desc(
2129  WDP_AUTO, "company_infrastructure", 0, 0,
2131  0,
2132  _nested_company_infrastructure_widgets, lengthof(_nested_company_infrastructure_widgets)
2133 );
2134 
2140 {
2141  if (!Company::IsValidID(company)) return;
2142  AllocateWindowDescFront<CompanyInfrastructureWindow>(&_company_infrastructure_desc, company);
2143 }
2144 
2145 static const NWidgetPart _nested_company_widgets[] = {
2147  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2148  NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), SetDataTip(STR_COMPANY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2149  NWidget(WWT_SHADEBOX, COLOUR_GREY),
2150  NWidget(WWT_STICKYBOX, COLOUR_GREY),
2151  EndContainer(),
2152  NWidget(WWT_PANEL, COLOUR_GREY),
2153  NWidget(NWID_HORIZONTAL), SetPIP(4, 6, 4),
2154  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2155  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2156  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2157  EndContainer(),
2160  NWidget(NWID_VERTICAL), SetPIP(4, 5, 5),
2161  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INAUGURATION), SetDataTip(STR_COMPANY_VIEW_INAUGURATED_TITLE, STR_NULL), SetFill(1, 0),
2162  NWidget(NWID_HORIZONTAL), SetPIP(0, 5, 0),
2163  NWidget(WWT_LABEL, COLOUR_GREY, WID_C_DESC_COLOUR_SCHEME), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE, STR_NULL),
2164  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME_EXAMPLE), SetMinimalSize(30, 0), SetFill(0, 1),
2165  NWidget(NWID_SPACER), SetFill(1, 0),
2166  EndContainer(),
2167  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2169  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_VEHICLE), SetDataTip(STR_COMPANY_VIEW_VEHICLES_TITLE, STR_NULL),
2170  NWidget(NWID_SPACER), SetFill(0, 1),
2171  EndContainer(),
2173  NWidget(NWID_SPACER), SetFill(1, 0),
2174  EndContainer(),
2175  EndContainer(),
2176  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2178  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),
2179  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),
2180  EndContainer(),
2181  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_RELOCATE),
2182  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
2184  EndContainer(),
2185  NWidget(NWID_SPACER), SetFill(0, 1),
2186  EndContainer(),
2187  EndContainer(),
2188  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_COMPANY_VALUE), SetDataTip(STR_COMPANY_VIEW_COMPANY_VALUE, STR_NULL), SetFill(1, 0),
2189  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2190  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2192  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE, STR_NULL),
2193  NWidget(NWID_SPACER), SetFill(0, 1),
2194  EndContainer(),
2197  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2198  NWidget(NWID_SPACER), SetFill(0, 1), SetMinimalSize(90, 0),
2199  EndContainer(),
2200  EndContainer(),
2201  EndContainer(),
2204  NWidget(NWID_VERTICAL), SetPIP(5, 5, 4),
2205  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_OWNERS), SetMinimalTextLines(3, 0),
2206  NWidget(NWID_SPACER), SetFill(0, 1),
2207  EndContainer(),
2208  EndContainer(),
2209  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2210  NWidget(NWID_SPACER), SetMinimalSize(90, 0), SetFill(0, 1),
2211  /* Multi player buttons. */
2213  NWidget(WWT_EMPTY, COLOUR_GREY, WID_C_HAS_PASSWORD),
2215  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_PASSWORD), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_COMPANY_VIEW_PASSWORD_TOOLTIP),
2216  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2217  EndContainer(),
2218  EndContainer(),
2219  EndContainer(),
2220  EndContainer(),
2221  EndContainer(),
2222  EndContainer(),
2223  EndContainer(),
2224  /* Button bars at the bottom. */
2225  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_BUTTONS),
2227  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),
2228  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),
2229  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),
2230  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),
2231  EndContainer(),
2233  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),
2234  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),
2235  EndContainer(),
2236  EndContainer(),
2237 };
2238 
2239 int GetAmountOwnedBy(const Company *c, Owner owner)
2240 {
2241  return (c->share_owners[0] == owner) +
2242  (c->share_owners[1] == owner) +
2243  (c->share_owners[2] == owner) +
2244  (c->share_owners[3] == owner);
2245 }
2246 
2249  STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2250 };
2251 
2256 {
2257  CompanyWidgets query_widget;
2258 
2261  /* Display planes of the #WID_C_SELECT_MULTIPLAYER selection widget. */
2262  CWP_MP_C_PWD = 0,
2264 
2265  /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2266  CWP_VB_VIEW = 0,
2268 
2269  /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2270  CWP_RELOCATE_SHOW = 0,
2272 
2273  /* Display planes of the #WID_C_SELECT_BUTTONS selection widget. */
2274  CWP_BUTTONS_LOCAL = 0,
2276  };
2277 
2278  CompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2279  {
2280  this->InitNested(window_number);
2281  this->owner = (Owner)this->window_number;
2282  this->OnInvalidateData();
2283  }
2284 
2285  void OnPaint() override
2286  {
2287  const Company *c = Company::Get((CompanyID)this->window_number);
2288  bool local = this->window_number == _local_company;
2289 
2290  if (!this->IsShaded()) {
2291  bool reinit = false;
2292 
2293  /* Button bar selection. */
2294  int plane = local ? CWP_BUTTONS_LOCAL : CWP_BUTTONS_OTHER;
2295  NWidgetStacked *wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS);
2296  if (plane != wi->shown_plane) {
2297  wi->SetDisplayedPlane(plane);
2298  this->InvalidateData();
2299  return;
2300  }
2301 
2302  /* Build HQ button handling. */
2303  plane = (local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW;
2304  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ);
2305  if (plane != wi->shown_plane) {
2306  wi->SetDisplayedPlane(plane);
2307  this->SetDirty();
2308  return;
2309  }
2310 
2311  this->SetWidgetDisabledState(WID_C_VIEW_HQ, c->location_of_HQ == INVALID_TILE);
2312 
2313  /* Enable/disable 'Relocate HQ' button. */
2314  plane = (!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW;
2315  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE);
2316  if (plane != wi->shown_plane) {
2317  wi->SetDisplayedPlane(plane);
2318  this->SetDirty();
2319  return;
2320  }
2321 
2322  /* Owners of company */
2323  plane = SZSP_HORIZONTAL;
2324  for (uint i = 0; i < lengthof(c->share_owners); i++) {
2325  if (c->share_owners[i] != INVALID_COMPANY) {
2326  plane = 0;
2327  break;
2328  }
2329  }
2330  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_DESC_OWNERS);
2331  if (plane != wi->shown_plane) {
2332  wi->SetDisplayedPlane(plane);
2333  reinit = true;
2334  }
2335 
2336  /* Multiplayer buttons. */
2337  plane = ((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN));
2338  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER);
2339  if (plane != wi->shown_plane) {
2340  wi->SetDisplayedPlane(plane);
2341  reinit = true;
2342  }
2343  this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
2344 
2345  if (reinit) {
2346  this->ReInit();
2347  return;
2348  }
2349  }
2350 
2351  this->DrawWidgets();
2352  }
2353 
2354  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2355  {
2356  switch (widget) {
2357  case WID_C_FACE: {
2358  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
2359  size->width = max(size->width, face_size.width);
2360  size->height = max(size->height, face_size.height);
2361  break;
2362  }
2363 
2365  Point offset;
2366  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2367  d.width -= offset.x;
2368  d.height -= offset.y;
2369  *size = maxdim(*size, d);
2370  break;
2371  }
2372 
2374  SetDParam(0, INT64_MAX); // Arguably the maximum company value
2375  size->width = GetStringBoundingBox(STR_COMPANY_VIEW_COMPANY_VALUE).width;
2376  break;
2377 
2379  SetDParamMaxValue(0, 5000); // Maximum number of vehicles
2380  for (uint i = 0; i < lengthof(_company_view_vehicle_count_strings); i++) {
2381  size->width = max(size->width, GetStringBoundingBox(_company_view_vehicle_count_strings[i]).width);
2382  }
2383  break;
2384 
2386  SetDParamMaxValue(0, UINT_MAX);
2387  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL).width);
2388  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD).width);
2389  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER).width);
2390  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION).width);
2391  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT).width);
2392  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE).width);
2393  break;
2394 
2395  case WID_C_DESC_OWNERS: {
2396  for (const Company *c2 : Company::Iterate()) {
2397  SetDParamMaxValue(0, 75);
2398  SetDParam(1, c2->index);
2399 
2400  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_SHARES_OWNED_BY).width);
2401  }
2402  break;
2403  }
2404 
2405  case WID_C_HAS_PASSWORD:
2406  *size = maxdim(*size, GetSpriteSize(SPR_LOCK));
2407  break;
2408  }
2409  }
2410 
2411  void DrawWidget(const Rect &r, int widget) const override
2412  {
2413  const Company *c = Company::Get((CompanyID)this->window_number);
2414  switch (widget) {
2415  case WID_C_FACE:
2416  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2417  break;
2418 
2419  case WID_C_FACE_TITLE:
2420  SetDParam(0, c->index);
2421  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
2422  break;
2423 
2425  Point offset;
2426  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2427  d.height -= offset.y;
2428  DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, (r.top + r.bottom - d.height) / 2 - offset.y);
2429  break;
2430  }
2431 
2433  uint amounts[4];
2434  amounts[0] = c->group_all[VEH_TRAIN].num_vehicle;
2435  amounts[1] = c->group_all[VEH_ROAD].num_vehicle;
2436  amounts[2] = c->group_all[VEH_SHIP].num_vehicle;
2437  amounts[3] = c->group_all[VEH_AIRCRAFT].num_vehicle;
2438 
2439  int y = r.top;
2440  if (amounts[0] + amounts[1] + amounts[2] + amounts[3] == 0) {
2441  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2442  } else {
2443  assert_compile(lengthof(amounts) == lengthof(_company_view_vehicle_count_strings));
2444 
2445  for (uint i = 0; i < lengthof(amounts); i++) {
2446  if (amounts[i] != 0) {
2447  SetDParam(0, amounts[i]);
2448  DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[i]);
2449  y += FONT_HEIGHT_NORMAL;
2450  }
2451  }
2452  }
2453  break;
2454  }
2455 
2457  uint y = r.top;
2458 
2459  /* Collect rail and road counts. */
2460  uint rail_pieces = c->infrastructure.signal;
2461  uint road_pieces = 0;
2462  for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pieces += c->infrastructure.rail[i];
2463  for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
2464 
2465  if (rail_pieces == 0 && road_pieces == 0 && c->infrastructure.water == 0 && c->infrastructure.station == 0 && c->infrastructure.airport == 0) {
2466  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2467  } else {
2468  if (rail_pieces != 0) {
2469  SetDParam(0, rail_pieces);
2470  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
2471  y += FONT_HEIGHT_NORMAL;
2472  }
2473  if (road_pieces != 0) {
2474  SetDParam(0, road_pieces);
2475  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
2476  y += FONT_HEIGHT_NORMAL;
2477  }
2478  if (c->infrastructure.water != 0) {
2480  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
2481  y += FONT_HEIGHT_NORMAL;
2482  }
2483  if (c->infrastructure.station != 0) {
2485  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
2486  y += FONT_HEIGHT_NORMAL;
2487  }
2488  if (c->infrastructure.airport != 0) {
2490  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
2491  }
2492  }
2493 
2494  break;
2495  }
2496 
2497  case WID_C_DESC_OWNERS: {
2498  uint y = r.top;
2499 
2500  for (const Company *c2 : Company::Iterate()) {
2501  uint amt = GetAmountOwnedBy(c, c2->index);
2502  if (amt != 0) {
2503  SetDParam(0, amt * 25);
2504  SetDParam(1, c2->index);
2505 
2506  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_SHARES_OWNED_BY);
2507  y += FONT_HEIGHT_NORMAL;
2508  }
2509  }
2510  break;
2511  }
2512 
2513  case WID_C_HAS_PASSWORD:
2515  DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top);
2516  }
2517  break;
2518  }
2519  }
2520 
2521  void SetStringParameters(int widget) const override
2522  {
2523  switch (widget) {
2524  case WID_C_CAPTION:
2525  SetDParam(0, (CompanyID)this->window_number);
2526  SetDParam(1, (CompanyID)this->window_number);
2527  break;
2528 
2530  SetDParam(0, Company::Get((CompanyID)this->window_number)->inaugurated_year);
2531  break;
2532 
2534  SetDParam(0, CalculateCompanyValue(Company::Get((CompanyID)this->window_number)));
2535  break;
2536  }
2537  }
2538 
2539  void OnClick(Point pt, int widget, int click_count) override
2540  {
2541  switch (widget) {
2542  case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2543 
2544  case WID_C_COLOUR_SCHEME:
2545  ShowCompanyLiveryWindow((CompanyID)this->window_number, INVALID_GROUP);
2546  break;
2547 
2548  case WID_C_PRESIDENT_NAME:
2549  this->query_widget = WID_C_PRESIDENT_NAME;
2550  SetDParam(0, this->window_number);
2551  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);
2552  break;
2553 
2554  case WID_C_COMPANY_NAME:
2555  this->query_widget = WID_C_COMPANY_NAME;
2556  SetDParam(0, this->window_number);
2557  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);
2558  break;
2559 
2560  case WID_C_VIEW_HQ: {
2561  TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
2562  if (_ctrl_pressed) {
2564  } else {
2565  ScrollMainWindowToTile(tile);
2566  }
2567  break;
2568  }
2569 
2570  case WID_C_BUILD_HQ:
2571  if ((byte)this->window_number != _local_company) return;
2572  if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2574  this->RaiseButtons();
2575  break;
2576  }
2577  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2578  SetTileSelectSize(2, 2);
2579  this->LowerWidget(WID_C_BUILD_HQ);
2580  this->SetWidgetDirty(WID_C_BUILD_HQ);
2581  break;
2582 
2583  case WID_C_RELOCATE_HQ:
2584  if (this->IsWidgetLowered(WID_C_RELOCATE_HQ)) {
2586  this->RaiseButtons();
2587  break;
2588  }
2589  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2590  SetTileSelectSize(2, 2);
2591  this->LowerWidget(WID_C_RELOCATE_HQ);
2592  this->SetWidgetDirty(WID_C_RELOCATE_HQ);
2593  break;
2594 
2596  ShowCompanyInfrastructure((CompanyID)this->window_number);
2597  break;
2598 
2599  case WID_C_BUY_SHARE:
2600  DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
2601  break;
2602 
2603  case WID_C_SELL_SHARE:
2604  DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
2605  break;
2606 
2608  if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
2609  break;
2610 
2611  case WID_C_COMPANY_JOIN: {
2612  this->query_widget = WID_C_COMPANY_JOIN;
2613  CompanyID company = (CompanyID)this->window_number;
2614  if (_network_server) {
2617  } else if (NetworkCompanyIsPassworded(company)) {
2618  /* ask for the password */
2619  ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, this, CS_ALPHANUMERAL, QSF_PASSWORD);
2620  } else {
2621  /* just send the join command */
2622  NetworkClientRequestMove(company);
2623  }
2624  break;
2625  }
2626  }
2627  }
2628 
2629  void OnHundredthTick() override
2630  {
2631  /* redraw the window every now and then */
2632  this->SetDirty();
2633  }
2634 
2635  void OnPlaceObject(Point pt, TileIndex tile) override
2636  {
2637  if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)) && !_shift_pressed) {
2639  this->RaiseButtons();
2640  }
2641  }
2642 
2643  void OnPlaceObjectAbort() override
2644  {
2645  this->RaiseButtons();
2646  }
2647 
2648  void OnQueryTextFinished(char *str) override
2649  {
2650  if (str == nullptr) return;
2651 
2652  switch (this->query_widget) {
2653  default: NOT_REACHED();
2654 
2655  case WID_C_PRESIDENT_NAME:
2656  DoCommandP(0, 0, 0, CMD_RENAME_PRESIDENT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_PRESIDENT), nullptr, str);
2657  break;
2658 
2659  case WID_C_COMPANY_NAME:
2660  DoCommandP(0, 0, 0, CMD_RENAME_COMPANY | CMD_MSG(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME), nullptr, str);
2661  break;
2662 
2663  case WID_C_COMPANY_JOIN:
2664  NetworkClientRequestMove((CompanyID)this->window_number, str);
2665  break;
2666  }
2667  }
2668 
2669 
2675  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2676  {
2677  if (this->window_number == _local_company) return;
2678 
2679  if (_settings_game.economy.allow_shares) { // Shares are allowed
2680  const Company *c = Company::Get(this->window_number);
2681 
2682  /* If all shares are owned by someone (none by nobody), disable buy button */
2683  this->SetWidgetDisabledState(WID_C_BUY_SHARE, GetAmountOwnedBy(c, INVALID_OWNER) == 0 ||
2684  /* Only 25% left to buy. If the company is human, disable buying it up.. TODO issues! */
2685  (GetAmountOwnedBy(c, INVALID_OWNER) == 1 && !c->is_ai) ||
2686  /* Spectators cannot do anything of course */
2688 
2689  /* If the company doesn't own any shares, disable sell button */
2690  this->SetWidgetDisabledState(WID_C_SELL_SHARE, (GetAmountOwnedBy(c, _local_company) == 0) ||
2691  /* Spectators cannot do anything of course */
2693  } else { // Shares are not allowed, disable buy/sell buttons
2694  this->DisableWidget(WID_C_BUY_SHARE);
2695  this->DisableWidget(WID_C_SELL_SHARE);
2696  }
2697  }
2698 };
2699 
2700 static WindowDesc _company_desc(
2701  WDP_AUTO, "company", 0, 0,
2703  0,
2704  _nested_company_widgets, lengthof(_nested_company_widgets)
2705 );
2706 
2711 void ShowCompany(CompanyID company)
2712 {
2713  if (!Company::IsValidID(company)) return;
2714 
2715  AllocateWindowDescFront<CompanyWindow>(&_company_desc, company);
2716 }
2717 
2723 {
2724  SetWindowDirty(WC_COMPANY, company);
2726 }
2727 
2729  BuyCompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2730  {
2731  this->InitNested(window_number);
2732  }
2733 
2734  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2735  {
2736  switch (widget) {
2737  case WID_BC_FACE:
2738  *size = GetSpriteSize(SPR_GRADIENT);
2739  break;
2740 
2741  case WID_BC_QUESTION:
2742  const Company *c = Company::Get((CompanyID)this->window_number);
2743  SetDParam(0, c->index);
2744  SetDParam(1, c->bankrupt_value);
2745  size->height = GetStringHeight(STR_BUY_COMPANY_MESSAGE, size->width);
2746  break;
2747  }
2748  }
2749 
2750  void SetStringParameters(int widget) const override
2751  {
2752  switch (widget) {
2753  case WID_BC_CAPTION:
2754  SetDParam(0, STR_COMPANY_NAME);
2755  SetDParam(1, Company::Get((CompanyID)this->window_number)->index);
2756  break;
2757  }
2758  }
2759 
2760  void DrawWidget(const Rect &r, int widget) const override
2761  {
2762  switch (widget) {
2763  case WID_BC_FACE: {
2764  const Company *c = Company::Get((CompanyID)this->window_number);
2765  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2766  break;
2767  }
2768 
2769  case WID_BC_QUESTION: {
2770  const Company *c = Company::Get((CompanyID)this->window_number);
2771  SetDParam(0, c->index);
2772  SetDParam(1, c->bankrupt_value);
2773  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING, SA_CENTER);
2774  break;
2775  }
2776  }
2777  }
2778 
2779  void OnClick(Point pt, int widget, int click_count) override
2780  {
2781  switch (widget) {
2782  case WID_BC_NO:
2783  delete this;
2784  break;
2785 
2786  case WID_BC_YES:
2787  DoCommandP(0, this->window_number, 0, CMD_BUY_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_COMPANY));
2788  break;
2789  }
2790  }
2791 };
2792 
2793 static const NWidgetPart _nested_buy_company_widgets[] = {
2795  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2796  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2797  EndContainer(),
2798  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2799  NWidget(NWID_VERTICAL), SetPIP(8, 8, 8),
2800  NWidget(NWID_HORIZONTAL), SetPIP(8, 10, 8),
2801  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2802  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2803  EndContainer(),
2804  NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(100, 10, 100),
2805  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
2806  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
2807  EndContainer(),
2808  EndContainer(),
2809  EndContainer(),
2810 };
2811 
2812 static WindowDesc _buy_company_desc(
2813  WDP_AUTO, nullptr, 0, 0,
2816  _nested_buy_company_widgets, lengthof(_nested_buy_company_widgets)
2817 );
2818 
2824 {
2825  AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, company);
2826 }
Button to view the HQ.
Functions related to OTTD&#39;s strings.
Owner
Enum for all companies/owners.
Definition: company_type.h:18
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
Button to make new face.
Empty widget, place holder to reserve space in widget array.
Definition: widget_type.h:46
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Base types for having sorted lists in GUIs.
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:18
void RebuildDone()
Notify the sortlist that the rebuild is done.
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:79
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:471
Text about collar.
bool _networking
are we in networking mode?
Definition: network.cpp:52
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:304
Tie / Earring right.
Title for the face.
static const uint8 PC_WHITE
White palette colour.
Definition: gfx_func.h:206
Horizontally center the text.
Definition: gfx_func.h:95
Window with detailed information about the company&#39;s infrastructure.
static NWidgetPart SetResize(int16 dx, int16 dy)
Widget part function for setting the resize step.
Definition: widget_type.h:928
Select panel or nothing.
Button to relocate the HQ.
VehicleType vehicle_type
Vehicle type of the group.
Definition: group.h:68
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:110
LiveryScheme
List of different livery schemes.
Definition: livery.h:20
Dropdown for secondary colour.
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Invalid expense type.
Definition: economy_type.h:163
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
Button to change company name.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3215
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
byte landscape
the landscape we&#39;re currently in
Button to join company.
Caption of the window.
High level window description.
Definition: window_gui.h:166
An invalid owner.
Definition: company_type.h:29
Has company password lock.
void OnResize() override
Called after the window got resized.
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
Train vehicle type.
Definition: vehicle_type.h:24
Text about moustache and earring.
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:291
Text about hair.
Functions related to dates.
Chin right.
RoadTypes
The different roadtypes we support, but then a bitmask of them.
Definition: road_type.h:36
const uint length
Number of items in list.
Definition: company_gui.cpp:92
Centered label.
Definition: widget_type.h:55
GUIs related to networking.
static T ToggleBit(T &x, const uint8 y)
Toggles a bit in a variable.
Scrollbar data structure.
Definition: widget_type.h:587
Stacked widgets, widgets all occupying the same space in the window.
Definition: widget_type.h:403
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:47
uint32 GetRailTotal() const
Get total sum of all owned track bits.
Definition: company_base.h:38
View company infrastructure.
#define FOR_ALL_SORTED_ROADTYPES(var)
Loop header for iterating over roadtypes, sorted by sortorder.
Definition: road.h:312
Year inaugurated_year
Year of starting the company.
Definition: company_base.h:78
Offset at top to draw the frame rectangular area.
Definition: window_gui.h:62
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:73
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:2423
Toggle for large or small.
Arrow to the right or in case of RTL to the left.
Definition: widget_type.h:36
Arrow to the left or in case of RTL to the right.
Definition: widget_type.h:35
Text about nose.
void OnPlaceObject(Point pt, TileIndex tile) override
The user clicked some place on the map when a tile highlight mode has been set.
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:1119
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:76
Ship vehicle type.
Definition: vehicle_type.h:26
Glasses left.
Rail specific functions.
void OnPlaceObjectAbort() override
The user cancelled a tile highlight mode that has been set.
void OnPaint() override
The window must be repainted.
Used for iterations.
Definition: road_type.h:26
Column for year Y-1 expenses.
VehicleType
Available vehicle types.
Definition: vehicle_type.h:21
Toggle for large or small.
Road specific functions.
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:189
const ExpensesType * et
Expenses items.
Definition: company_gui.cpp:91
Button to change colour scheme.
Resize box (normally at bottom-right of a window)
Definition: widget_type.h:66
Buyout company (merger); Window numbers:
Definition: window_type.h:577
Caption of the window.
void SetPosition(int position)
Sets the position of the first visible element.
Definition: widget_type.h:699
Create random new face.
Caption of window.
Types related to the company widgets.
uint32 GetTramTotal() const
Get total sum of all owned tram bits.
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.
set the livery for a group
Definition: command_type.h:324
Description of road.
buy a company which is bankrupt
Definition: command_type.h:258
Jacket left.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
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:189
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=nullptr, uint textref_stack_size=0, const uint32 *textref_stack=nullptr)
Display an error message in a window.
Definition: error_gui.cpp:380
static Money SignalMaintenanceCost(uint32 num)
Calculates the maintenance cost of a number of signals.
Definition: rail.h:438
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:67
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:39
static NWidgetPart SetMinimalTextLines(uint8 lines, uint8 spacing, FontSize size=FS_NORMAL)
Widget part function for setting the minimal text lines.
Definition: widget_type.h:963
Other expenses.
Definition: economy_type.h:161
#define lastof(x)
Get the last element of an fixed size array.
Definition: depend.cpp:48
bool NetworkCompanyIsPassworded(CompanyID company_id)
Check if the company we want to join requires a password.
Definition: network.cpp:213
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:16
A male of Caucasian origin (white)
Construction costs.
Definition: economy_type.h:149
uint32 station
Count of company owned station tiles.
Definition: company_base.h:34
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:24
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:24
Tie / Earring.
bool infrastructure_maintenance
enable monthly maintenance fee for owner infrastructure
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Pure simple text.
Definition: widget_type.h:56
Description of station.
bool IsDisabled() const
Return whether the widget is disabled.
Definition: widget_type.h:356
Caption of window.
bool NeedRebuild() const
Check if a rebuild is needed.
Functions, definitions and such used only by the GUI.
Description of tram.
No rail types.
Definition: rail_type.h:47
void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
Helper for drawing the counts line.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
Column for year Y-2 expenses.
void SetCount(int num)
Sets the number of elements in the list.
Definition: widget_type.h:668
Income from ships.
Definition: economy_type.h:159
bool allow_shares
allow the buying/selling of shares
Partial widget specification to allow NWidgets to be written nested.
Definition: widget_type.h:908
Functions related to (drawing on) viewports.
void ForceRebuild()
Force that a rebuild is needed.
static const int LEVEL_WIDTH
Indenting width of a sub-group in pixels.
Running costs aircraft.
Definition: economy_type.h:153
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:276
No button.
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:35
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:1030
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:1044
Hair right.
Bottom offset of the text of the frame.
Definition: window_gui.h:73
Female button in the advanced view.
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:21
StringID name
Name of this rail type.
Definition: road.h:100
static const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
Definition: road.h:224
Yes button.
uint32 CompanyManagerFace
Company manager face bits, info see in company_manager_face.h.
Definition: company_type.h:51
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:31
Invisible widget that takes some space.
Definition: widget_type.h:77
decrease the loan from the bank
Definition: command_type.h:238
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.
Colour scheme example.
int GetScrolledRowFromWidget(int clickpos, const Window *const w, int widget, int padding=0, int line_height=-1) const
Compute the row of a scrolled widget that a user clicked in.
Definition: widget.cpp:1957
void OnPaint() override
The window must be repainted.
This window is used for construction; close it whenever changing company.
Definition: window_gui.h:208
The client is spectating.
Definition: company_type.h:35
void SetDataTip(uint32 widget_data, StringID tool_tip)
Set data and tool tip of the nested widget.
Definition: widget.cpp:892
RoadTypes AddDateIntroducedRoadTypes(RoadTypes current, Date date)
Add the road types that are to be introduced at the given date.
Definition: road.cpp:155
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:237
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.
void OnQueryTextFinished(char *str) override
The query window opened from this window has closed.
Count of rail.
void OnQueryTextFinished(char *str) override
The query window opened from this window has closed.
Count of water.
Money current_loan
Amount of money borrowed from the bank.
Definition: company_base.h:67
#define FONT_HEIGHT_NORMAL
Height of characters in the normal (FS_NORMAL) font.
Definition: gfx_func.h:176
static NWidgetPart SetDataTip(uint32 data, StringID tip)
Widget part function for setting the data and tooltip.
Definition: widget_type.h:1012
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:78
Display plane with zero size vertically, and filling and resizing horizontally.
Definition: widget_type.h:387
static NWidgetPart SetMinimalSize(int16 x, int16 y)
Widget part function for setting the minimal size.
Definition: widget_type.h:945
Interest payments over the loan.
Definition: economy_type.h:160
Money AirportMaintenanceCost(Owner owner)
Calculates the maintenance cost of all airports of a company.
Definition: station.cpp:653
TileIndex location_of_HQ
Northern tile of HQ; INVALID_TILE when there is none.
Definition: company_base.h:73
Definition of base types and functions in a cross-platform compatible way.
Center both horizontally and vertically.
Definition: gfx_func.h:104
static Money RoadMaintenanceCost(RoadType roadtype, uint32 num, uint32 total_num)
Calculates the maintenance cost of a number of road bits.
Definition: road_func.h:125
the length of the string is counted in characters
Definition: textbuf_gui.h:22
uint32 GetRoadTotal() const
Get total sum of all owned road bits.
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:40
uint32 road[ROADTYPE_END]
Count of company owned track bits for each road type.
Definition: company_base.h:30
A number of safeguards to prevent using unsafe methods.
GenderEthnicity ge
Gender and ethnicity.
Load face.
Normal push-button (no toggle button) with text caption.
Definition: widget_type.h:102
RailTypes introduces_railtypes
Bitmask of which other railtypes are introduced when this railtype is introduced. ...
Definition: rail.h:263
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:48
Window class displaying the company finances.
uint16 GroupID
Type for all group identifiers.
Definition: group_type.h:13
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:234
Finances of a company; Window numbers:
Definition: window_type.h:516
Information about a particular livery.
Definition: livery.h:78
int pos_x
Horizontal position of top-left corner of the widget in the window.
Definition: widget_type.h:175
Tie / Earring left.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
RailTypes railtypes
Valid railtypes.
static const byte LIT_ALL
Show the liveries of all companies.
Definition: livery.h:17
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:223
CompanyWidgets
Widgets of the CompanyWindow class.
GroupStatistics group_all[VEH_COMPANY_END]
NOSAVE: Statistics for the ALL_GROUP group.
Definition: company_base.h:128
change the company name
Definition: command_type.h:244
Money CalculateCompanyValue(const Company *c, bool including_loan=true)
Calculate the value of the company.
Definition: economy.cpp:111
set the colour of the company
Definition: command_type.h:235
Gap above max loan widget.
bool is_ai
If true, the company is (also) controlled by the computer (a NoAI program).
Definition: company_base.h:93
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:1112
Money money
Money owned by the company.
Definition: company_base.h:65
Offset at bottom to draw the frame rectangular area.
Definition: window_gui.h:63
Dropdown for primary colour.
Baseclass for nested widgets.
Definition: widget_type.h:124
static const GroupID INVALID_GROUP
Sentinel for invalid groups.
Definition: group_type.h:18
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:498
Basic functions/variables used all over the place.
Current face.
uint16 num_vehicle
Number of vehicles.
Definition: group.h:25
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:532
uint32 airport
Count of company owned airports.
Definition: company_base.h:35
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:40
Lips / Moustache right.
Grid of rows and columns.
Definition: widget_type.h:57
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:40
Display plane with zero size in both directions (none filling and resizing).
Definition: widget_type.h:388
Right offset of the image in the button.
Definition: window_gui.h:39
RailTypes
The different railtypes we support, but then a bitmask of them.
Definition: rail_type.h:46
uint GetCategoriesWidth() const
Compute width of the expenses categories in pixels.
Income from aircraft.
Definition: economy_type.h:158
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
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.
bool Sort(SortFunction *compare)
Sort the list.
Money max_loan
NOSAVE: Maximum possible loan.
Definition: economy_type.h:20
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:16
Text is written left-to-right by default.
Definition: strings_type.h:23
static const uint8 PC_BLACK
Black palette colour.
Definition: gfx_func.h:203
Infrastructure count.
byte colour2
Second colour, for vehicles with 2CC support.
Definition: livery.h:81
Text about chin.
Count of road.
CompanyManagerFace face
Face description of the president.
Definition: company_base.h:63
const uint num_subtotals
Number of sub-totals in the list.
Definition: company_gui.cpp:93
void OnHundredthTick() override
Called once every 100 (game) ticks.
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:20
Text about lips and moustache.
static SpriteID GetCompanyManagerFaceSprite(CompanyManagerFace cmf, CompanyManagerFaceVariable cmfv, GenderEthnicity ge)
Gets the sprite to draw for the given company manager&#39;s face variable.
void OnInit() override
Notification that the nested widget tree gets initialized.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:137
Eyecolour left.
bool _shift_pressed
Is Shift pressed?
Definition: gfx.cpp:36
void ShowExtraViewPortWindow(TileIndex tile=INVALID_TILE)
Show a new Extra Viewport window.
void OnPaint() override
The window must be repainted.
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:700
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
uint16 GetCount() const
Gets the number of elements in the list.
Definition: widget_type.h:611
Increase loan.
void ForceResort()
Force a resort next Sort call Reset the resort timer if used too.
Livery livery
Custom colour scheme for vehicles in this group.
Definition: group.h:71
Dimension maxdim(const Dimension &d1, const Dimension &d2)
Compute bounding box of both dimensions.
Owner share_owners[4]
Owners of the 4 shares of the company. INVALID_OWNER if nobody has bought them yet.
Definition: company_base.h:76
CompanyInfrastructure infrastructure
NOSAVE: Counts of company owned infrastructure.
Definition: company_base.h:131
Lips / Moustache left.
uint32 rail[RAILTYPE_END]
Count of company owned track bits for each rail type.
Definition: company_base.h:32
No window, redirects to WC_MAIN_WINDOW.
Definition: window_type.h:38
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:570
Text about eyebrows.
Functions related to companies.
Collar right.
An invalid company.
Definition: company_type.h:30
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:3290
Count of total.
Matrix scrollbar.
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition: sprites.h:1556
Used for iterations.
Definition: road_type.h:23
Base class for engines.
Count of tram.
Description of water.
Both numeric and alphabetic and spaces and stuff.
Definition: string_type.h:27
RailType
Enumeration for all possible railtypes.
Definition: rail_type.h:27
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
Toggle windows size.
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:341
GUISettings gui
settings related to the GUI
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition: pool_type.hpp:340
GroupID parent
Parent group.
Definition: group.h:76
Running costs trains.
Definition: economy_type.h:151
Window caption (window title between closebox and stickybox)
Definition: widget_type.h:59
int strnatcmp(const char *s1, const char *s2, bool ignore_garbage_at_front)
Compares two strings using case insensitive natural sort.
Definition: string.cpp:578
Description of total.
static bool StrEmpty(const char *s)
Check if a string buffer is empty.
Definition: string_func.h:57
static Money StationMaintenanceCost(uint32 num)
Calculates the maintenance cost of a number of station tiles.
Definition: station_func.h:65
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
sell a share from a company
Definition: command_type.h:257
Class general.
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp:48
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
byte colour
Company colour.
Definition: company_base.h:69
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:104
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.
Property costs.
Definition: economy_type.h:155
Decrease loan..
Count of station.
Vertical container.
Definition: widget_type.h:75
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:997
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:245
Functions related to zooming.
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:418
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:172
Panel about &#39;Relocate HQ&#39;.
#define endof(x)
Get the end element of an fixed size array.
Definition: stdafx.h:384
Get the face code.
LiveryClass
List of different livery classes, used only by the livery GUI.
Definition: livery.h:64
void OnPaint() override
The window must be repainted.
#define MAX_DAY
The number of days till the last day.
Definition: date_type.h:95
Group data.
Definition: group.h:65
bool has_2CC
Set if any vehicle is loaded which uses 2cc (two company colours).
Definition: newgrf.h:175
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
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:229
bool ScrollMainWindowToTile(TileIndex tile, bool instant)
Scrolls the viewport of the main window to a given location.
Definition: viewport.cpp:2396
Aircraft groups.
Button to buy a share.
Functions related to commands.
Network functions used by other parts of OpenTTD.
Text about eyecolour.
byte in_use
Bit 0 set if this livery should override the default livery first colour, Bit 1 for the second colour...
Definition: livery.h:79
bool _network_server
network-server is active
Definition: network.cpp:53
Coordinates of a point in 2D.
Dimension GetSpriteSize(SpriteID sprid, Point *offset, ZoomLevel zoom)
Get the size of a sprite.
Definition: gfx.cpp:770
void SetDisplayedPlane(int plane)
Select which plane to show (for NWID_SELECTION only).
Definition: widget.cpp:1082
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
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-nullptr) Titem.
Definition: pool_type.hpp:280
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:176
Drop down list.
Definition: widget_type.h:68
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Face button.
Eyebrows left.
Normal push-button (no toggle button) with arrow caption.
Definition: widget_type.h:104
Multiplayer selection panel.
uint16 GetCapacity() const
Gets the number of visible elements of the scrollbar.
Definition: widget_type.h:620
Caption of window.
Text about glasses.
Buttons of the other companies.
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
Running costs ships.
Definition: economy_type.h:154
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition: strings_type.h:17
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 ExpensesType category. ...
Definition: company_base.h:95
Aircraft vehicle type.
Definition: vehicle_type.h:27
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
GenderEthnicity
The gender/race combinations that we have faces for.
StringID name
Name of this rail type.
Definition: rail.h:173
Panel about infrastructure.
Offset at right to draw the frame rectangular area.
Definition: window_gui.h:61
byte liveries
options for displaying company liveries, 0=none, 1=self, 2=all
Definition: settings_type.h:99
Sticky box (at top-right of a window, after WWT_DEFSIZEBOX)
Definition: widget_type.h:64
Used for DoCommand-like (and some non-fatal AI GUI) errors/information.
Definition: error.h:21
Used for iterations.
Definition: rail_type.h:33
Class aircraft.
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
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:45
static NWidgetPart SetFill(uint fill_x, uint fill_y)
Widget part function for setting filling.
Definition: widget_type.h:981
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:83
byte colour1
First colour, for all vehicles.
Definition: livery.h:80
#define CMD_MSG(x)
Used to combine a StringID with the command.
Definition: command_type.h:368
Servers always have this ID.
Definition: network_type.h:41
int32 WindowNumber
Number to differentiate different windows of the same class.
Definition: window_type.h:705
GameCreationSettings game_creation
settings used during the creation of a game (map)
buy a share from a company
Definition: command_type.h:256
void SetCapacityFromWidget(Window *w, int widget, int padding=0)
Set capacity of visible elements from the size and resize properties of a widget. ...
Definition: widget.cpp:1971
void ResetObjectToPlace()
Reset the cursor and mouse mode handling back to default (normal cursor, only clicking in windows)...
Definition: viewport.cpp:3353
Question text.
Specification of a rectangle with absolute coordinates of all edges.
Vertical scrollbar.
Definition: widget_type.h:82
RoadTypes roadtypes
Valid roadtypes.
Income from road vehicles.
Definition: economy_type.h:157
Text is written right-to-left by default.
Definition: strings_type.h:24
Right align the text (must be a single bit).
Definition: gfx_func.h:96
WindowNumber window_number
Window number within the window class.
Definition: window_gui.h:312
Eyebrows right.
static void DrawYearColumn(const Rect &r, int year, const Money(*tbl)[EXPENSES_END])
Draw a column with prices.
New vehicles.
Definition: economy_type.h:150
Functions related to tile highlights.
uint total_width
String width of the total cost line.
Save face.
Window functions not directly related to making/drawing windows.
RoadTypes introduces_roadtypes
Bitmask of which other roadtypes are introduced when this roadtype is introduced. ...
Definition: road.h:174
void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
Update size and resize step of a widget in the window.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition: newgrf.cpp:76
Find a place automatically.
Definition: window_gui.h:154
Functions related to water (management)
(Toggle) Button with image
Definition: widget_type.h:50
void OnInvalidateData(int data=0, bool gui_scope=true) override
Some data on this window has become invalid.
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:78
password entry box, show warning about password security
Definition: textbuf_gui.h:23
Running costs road vehicles.
Definition: economy_type.h:152
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:427
Hide the relocate HQ button.
Window with general information about a company.
Income from trains.
Definition: economy_type.h:156
Number of expense types.
Definition: economy_type.h:162
void SetStringParameters(int widget) const override
Initialize string parameters for a widget.
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:362
Left offset of the image in the button.
Definition: window_gui.h:38
ExpensesType
Types of expenses.
Definition: economy_type.h:148
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
Male button in the simple view.
static NWidgetPart SetScrollbar(int index)
Attach a scrollbar to a widget.
Definition: widget_type.h:1093
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:44
Base list item class from which others are derived.
Definition: dropdown_type.h:22
Dimensions (a width and height) of a rectangle in 2D.
Value of the NCB_EQUALSIZE flag.
Definition: widget_type.h:427
void OnDropdownSelect(int widget, int index) override
A dropdown option associated to this window has been selected.
RailTypes AddDateIntroducedRailTypes(RailTypes current, Date date)
Add the rail types that are to be introduced at the given date.
Definition: rail.cpp:218
Offset at left to draw the frame rectangular area.
Definition: window_gui.h:60
static void ShowCompanyInfrastructure(CompanyID company)
Open the infrastructure window of a company.
void DrawWidget(const Rect &r, int widget) const override
Draw the contents of a nested widget.
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:1259
Shade box (at top-right of a window, between WWT_DEBUGBOX and WWT_DEFSIZEBOX)
Definition: widget_type.h:62
static const ObjectType OBJECT_HQ
HeadQuarter of a player.
Definition: object_type.h:20
Dimension yesno_dim
Dimension of a yes/no button of a part in the advanced face window.
Road vehicle type.
Definition: vehicle_type.h:25
Used for iterations.
Definition: rail_type.h:28
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:835
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:1074
No roadtypes.
Definition: road_type.h:37
bool is_moust_male
Male face with a moustache.
int pos_y
Vertical position of top-left corner of the widget in the window.
Definition: widget_type.h:176
Column for expenses category strings.
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:1462
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:621
(Toggle) Button with text
Definition: widget_type.h:53
void OnClick(Point pt, int widget, int click_count) override
A click with the left mouse button has been made on the window.
build an object
Definition: command_type.h:187
Description of rail.
uint16 GetPosition() const
Gets the position of the first visible element in the list.
Definition: widget_type.h:629
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:199
Base class for a &#39;real&#39; widget.
Definition: widget_type.h:282
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...
uint32 water
Count of company owned track bits for canals.
Definition: company_base.h:33
void OnHundredthTick() override
Called once every 100 (game) ticks.
Base for the NewGRF implementation.
static Pool::IterateWrapper< Engine > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition: engine_base.h:151