OpenTTD Source  1.10.3
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  void AddChildren(GUIGroupList *source, GroupID parent, int indent)
619  {
620  for (const Group *g : *source) {
621  if (g->parent != parent) continue;
622  this->groups.push_back(g);
623  this->indents.push_back(indent);
624  AddChildren(source, g->index, indent + 1);
625  }
626  }
627 
628  void BuildGroupList(CompanyID owner)
629  {
630  if (!this->groups.NeedRebuild()) return;
631 
632  this->groups.clear();
633  this->indents.clear();
634 
635  if (this->livery_class >= LC_GROUP_RAIL) {
636  GUIGroupList list;
637  VehicleType vtype = (VehicleType)(this->livery_class - LC_GROUP_RAIL);
638 
639  for (const Group *g : Group::Iterate()) {
640  if (g->owner == owner && g->vehicle_type == vtype) {
641  list.push_back(g);
642  }
643  }
644 
645  list.ForceResort();
646 
647  /* Sort the groups by their name */
648  const Group *last_group[2] = { nullptr, nullptr };
649  char last_name[2][64] = { "", "" };
650  list.Sort([&](const Group * const &a, const Group * const &b) -> bool {
651  if (a != last_group[0]) {
652  last_group[0] = a;
653  SetDParam(0, a->index);
654  GetString(last_name[0], STR_GROUP_NAME, lastof(last_name[0]));
655  }
656 
657  if (b != last_group[1]) {
658  last_group[1] = b;
659  SetDParam(0, b->index);
660  GetString(last_name[1], STR_GROUP_NAME, lastof(last_name[1]));
661  }
662 
663  int r = strnatcmp(last_name[0], last_name[1]); // Sort by name (natural sorting).
664  if (r == 0) return a->index < b->index;
665  return r < 0;
666  });
667 
668  AddChildren(&list, INVALID_GROUP, 0);
669  }
670 
671  this->groups.shrink_to_fit();
672  this->groups.RebuildDone();
673  }
674 
675  void SetRows()
676  {
677  if (this->livery_class < LC_GROUP_RAIL) {
678  this->rows = 0;
679  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
680  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
681  this->rows++;
682  }
683  }
684  } else {
685  this->rows = (uint)this->groups.size();
686  }
687 
688  this->vscroll->SetCount(this->rows);
689  }
690 
691 public:
692  SelectCompanyLiveryWindow(WindowDesc *desc, CompanyID company, GroupID group) : Window(desc)
693  {
694  this->CreateNestedTree();
695  this->vscroll = this->GetScrollbar(WID_SCL_MATRIX_SCROLLBAR);
696 
697  if (group == INVALID_GROUP) {
698  this->livery_class = LC_OTHER;
699  this->sel = 1;
700  this->LowerWidget(WID_SCL_CLASS_GENERAL);
701  this->BuildGroupList(company);
702  this->SetRows();
703  } else {
704  this->SetSelectedGroup(company, group);
705  }
706 
707  this->FinishInitNested(company);
708  this->owner = company;
709  this->InvalidateData(1);
710  }
711 
712  void SetSelectedGroup(CompanyID company, GroupID group)
713  {
714  this->RaiseWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
715  const Group *g = Group::Get(group);
716  switch (g->vehicle_type) {
717  case VEH_TRAIN: this->livery_class = LC_GROUP_RAIL; break;
718  case VEH_ROAD: this->livery_class = LC_GROUP_ROAD; break;
719  case VEH_SHIP: this->livery_class = LC_GROUP_SHIP; break;
720  case VEH_AIRCRAFT: this->livery_class = LC_GROUP_AIRCRAFT; break;
721  default: NOT_REACHED();
722  }
723  this->sel = group;
724  this->LowerWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
725 
726  this->groups.ForceRebuild();
727  this->BuildGroupList(company);
728  this->SetRows();
729 
730  /* Position scrollbar to selected group */
731  for (uint i = 0; i < this->rows; i++) {
732  if (this->groups[i]->index == sel) {
733  this->vscroll->SetPosition(Clamp(i - this->vscroll->GetCapacity() / 2, 0, max(this->vscroll->GetCount() - this->vscroll->GetCapacity(), 0)));
734  break;
735  }
736  }
737  }
738 
739  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
740  {
741  switch (widget) {
743  /* The matrix widget below needs enough room to print all the schemes. */
744  Dimension d = {0, 0};
745  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
746  d = maxdim(d, GetStringBoundingBox(STR_LIVERY_DEFAULT + scheme));
747  }
748 
749  /* And group names */
750  for (const Group *g : Group::Iterate()) {
751  if (g->owner == (CompanyID)this->window_number) {
752  SetDParam(0, g->index);
753  d = maxdim(d, GetStringBoundingBox(STR_GROUP_NAME));
754  }
755  }
756 
757  size->width = max(size->width, 5 + d.width + WD_FRAMERECT_RIGHT);
758  break;
759  }
760 
761  case WID_SCL_MATRIX: {
762  /* 11 items in the default rail class */
763  this->square = GetSpriteSize(SPR_SQUARE);
764  this->line_height = max(this->square.height, (uint)FONT_HEIGHT_NORMAL) + 4;
765 
766  size->height = 11 * this->line_height;
767  resize->width = 1;
768  resize->height = this->line_height;
769  break;
770  }
771 
774  size->width = 0;
775  break;
776  }
777  FALLTHROUGH;
778 
780  this->square = GetSpriteSize(SPR_SQUARE);
781  int padding = this->square.width + NWidgetScrollbar::GetVerticalDimension().width + 10;
782  for (const StringID *id = _colour_dropdown; id != endof(_colour_dropdown); id++) {
783  size->width = max(size->width, GetStringBoundingBox(*id).width + padding);
784  }
785  size->width = max(size->width, GetStringBoundingBox(STR_COLOUR_DEFAULT).width + padding);
786  break;
787  }
788  }
789  }
790 
791  void OnPaint() override
792  {
793  bool local = (CompanyID)this->window_number == _local_company;
794 
795  /* Disable dropdown controls if no scheme is selected */
796  bool disabled = this->livery_class < LC_GROUP_RAIL ? (this->sel == 0) : (this->sel == INVALID_GROUP);
797  this->SetWidgetDisabledState(WID_SCL_PRI_COL_DROPDOWN, !local || disabled);
798  this->SetWidgetDisabledState(WID_SCL_SEC_COL_DROPDOWN, !local || disabled);
799 
800  this->BuildGroupList((CompanyID)this->window_number);
801 
802  this->DrawWidgets();
803  }
804 
805  void SetStringParameters(int widget) const override
806  {
807  switch (widget) {
808  case WID_SCL_CAPTION:
809  SetDParam(0, (CompanyID)this->window_number);
810  break;
811 
814  const Company *c = Company::Get((CompanyID)this->window_number);
815  bool primary = widget == WID_SCL_PRI_COL_DROPDOWN;
816  StringID colour = STR_COLOUR_DEFAULT;
817 
818  if (this->livery_class < LC_GROUP_RAIL) {
819  if (this->sel != 0) {
820  LiveryScheme scheme = LS_DEFAULT;
821  for (scheme = LS_BEGIN; scheme < LS_END; scheme++) {
822  if (HasBit(this->sel, scheme)) break;
823  }
824  if (scheme == LS_END) scheme = LS_DEFAULT;
825  const Livery *livery = &c->livery[scheme];
826  if (scheme == LS_DEFAULT || HasBit(livery->in_use, primary ? 0 : 1)) {
827  colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
828  }
829  }
830  } else {
831  if (this->sel != INVALID_GROUP) {
832  const Group *g = Group::Get(this->sel);
833  const Livery *livery = &g->livery;
834  if (HasBit(livery->in_use, primary ? 0 : 1)) {
835  colour = STR_COLOUR_DARK_BLUE + (primary ? livery->colour1 : livery->colour2);
836  }
837  }
838  }
839  SetDParam(0, colour);
840  break;
841  }
842  }
843  }
844 
845  void DrawWidget(const Rect &r, int widget) const override
846  {
847  if (widget != WID_SCL_MATRIX) return;
848 
849  bool rtl = _current_text_dir == TD_RTL;
850 
851  /* Horizontal coordinates of scheme name column. */
852  const NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_SCL_SPACER_DROPDOWN);
853  int sch_left = nwi->pos_x;
854  int sch_right = sch_left + nwi->current_x - 1;
855  /* Horizontal coordinates of first dropdown. */
856  nwi = this->GetWidget<NWidgetBase>(WID_SCL_PRI_COL_DROPDOWN);
857  int pri_left = nwi->pos_x;
858  int pri_right = pri_left + nwi->current_x - 1;
859  /* Horizontal coordinates of second dropdown. */
860  nwi = this->GetWidget<NWidgetBase>(WID_SCL_SEC_COL_DROPDOWN);
861  int sec_left = nwi->pos_x;
862  int sec_right = sec_left + nwi->current_x - 1;
863 
864  int text_left = (rtl ? (uint)WD_FRAMERECT_LEFT : (this->square.width + 5));
865  int text_right = (rtl ? (this->square.width + 5) : (uint)WD_FRAMERECT_RIGHT);
866 
867  int square_offs = (this->line_height - this->square.height) / 2 + 1;
868  int text_offs = (this->line_height - FONT_HEIGHT_NORMAL) / 2 + 1;
869 
870  int y = r.top;
871 
872  /* Helper function to draw livery info. */
873  auto draw_livery = [&](StringID str, const Livery &liv, bool sel, bool def, int indent) {
874  /* Livery Label. */
875  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);
876 
877  /* Text below the first dropdown. */
878  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);
879  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);
880 
881  /* Text below the second dropdown. */
882  if (sec_right > sec_left) { // Second dropdown has non-zero size.
883  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);
884  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);
885  }
886 
887  y += this->line_height;
888  };
889 
890  if (livery_class < LC_GROUP_RAIL) {
891  int pos = this->vscroll->GetPosition();
892  const Company *c = Company::Get((CompanyID)this->window_number);
893  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
894  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
895  if (pos-- > 0) continue;
896  draw_livery(STR_LIVERY_DEFAULT + scheme, c->livery[scheme], HasBit(this->sel, scheme), scheme == LS_DEFAULT, 0);
897  }
898  }
899  } else {
900  uint max = min(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), (uint)this->groups.size());
901  for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
902  const Group *g = this->groups[i];
903  SetDParam(0, g->index);
904  draw_livery(STR_GROUP_NAME, g->livery, this->sel == g->index, false, this->indents[i] * LEVEL_WIDTH);
905  }
906  }
907  }
908 
909  void OnClick(Point pt, int widget, int click_count) override
910  {
911  switch (widget) {
912  /* Livery Class buttons */
914  case WID_SCL_CLASS_RAIL:
915  case WID_SCL_CLASS_ROAD:
916  case WID_SCL_CLASS_SHIP:
918  case WID_SCL_GROUPS_RAIL:
919  case WID_SCL_GROUPS_ROAD:
920  case WID_SCL_GROUPS_SHIP:
922  this->RaiseWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
923  this->livery_class = (LiveryClass)(widget - WID_SCL_CLASS_GENERAL);
924  this->LowerWidget(this->livery_class + WID_SCL_CLASS_GENERAL);
925 
926  /* Select the first item in the list */
927  if (this->livery_class < LC_GROUP_RAIL) {
928  this->sel = 0;
929  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
930  if (_livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme)) {
931  this->sel = 1 << scheme;
932  break;
933  }
934  }
935  } else {
936  this->sel = INVALID_GROUP;
937  this->groups.ForceRebuild();
938  this->BuildGroupList((CompanyID)this->window_number);
939 
940  if (this->groups.size() > 0) {
941  this->sel = this->groups[0]->index;
942  }
943  }
944 
945  this->SetRows();
946  this->SetDirty();
947  break;
948 
949  case WID_SCL_PRI_COL_DROPDOWN: // First colour dropdown
950  ShowColourDropDownMenu(WID_SCL_PRI_COL_DROPDOWN);
951  break;
952 
953  case WID_SCL_SEC_COL_DROPDOWN: // Second colour dropdown
954  ShowColourDropDownMenu(WID_SCL_SEC_COL_DROPDOWN);
955  break;
956 
957  case WID_SCL_MATRIX: {
958  uint row = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_SCL_MATRIX, 0, this->line_height);
959  if (row >= this->rows) return;
960 
961  if (this->livery_class < LC_GROUP_RAIL) {
962  LiveryScheme j = (LiveryScheme)row;
963 
964  for (LiveryScheme scheme = LS_BEGIN; scheme <= j && scheme < LS_END; scheme++) {
965  if (_livery_class[scheme] != this->livery_class || !HasBit(_loaded_newgrf_features.used_liveries, scheme)) j++;
966  }
967  assert(j < LS_END);
968 
969  if (_ctrl_pressed) {
970  ToggleBit(this->sel, j);
971  } else {
972  this->sel = 1 << j;
973  }
974  } else {
975  this->sel = this->groups[row]->index;
976  }
977  this->SetDirty();
978  break;
979  }
980  }
981  }
982 
983  void OnResize() override
984  {
985  this->vscroll->SetCapacityFromWidget(this, WID_SCL_MATRIX);
986  }
987 
988  void OnDropdownSelect(int widget, int index) override
989  {
990  bool local = (CompanyID)this->window_number == _local_company;
991  if (!local) return;
992 
993  if (index >= COLOUR_END) index = INVALID_COLOUR;
994 
995  if (this->livery_class < LC_GROUP_RAIL) {
996  /* Set company colour livery */
997  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
998  /* Changed colour for the selected scheme, or all visible schemes if CTRL is pressed. */
999  if (HasBit(this->sel, scheme) || (_ctrl_pressed && _livery_class[scheme] == this->livery_class && HasBit(_loaded_newgrf_features.used_liveries, scheme))) {
1000  DoCommandP(0, scheme | (widget == WID_SCL_PRI_COL_DROPDOWN ? 0 : 256), index, CMD_SET_COMPANY_COLOUR);
1001  }
1002  }
1003  } else {
1004  /* Setting group livery */
1005  DoCommandP(0, this->sel, (widget == WID_SCL_PRI_COL_DROPDOWN ? 0 : 256) | (index << 16), CMD_SET_GROUP_LIVERY);
1006  }
1007  }
1008 
1014  void OnInvalidateData(int data = 0, bool gui_scope = true) override
1015  {
1016  if (!gui_scope) return;
1017 
1018  if (data != -1) {
1019  /* data contains a VehicleType, rebuild list if it displayed */
1020  if (this->livery_class == data + LC_GROUP_RAIL) {
1021  this->groups.ForceRebuild();
1022  this->BuildGroupList((CompanyID)this->window_number);
1023  this->SetRows();
1024 
1025  if (!Group::IsValidID(this->sel)) {
1026  this->sel = INVALID_GROUP;
1027  if (this->groups.size() > 0) this->sel = this->groups[0]->index;
1028  }
1029 
1030  this->SetDirty();
1031  }
1032  return;
1033  }
1034 
1036 
1037  bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1038  if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
1039  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1041  if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1042  this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1043  } else if (this->livery_class < LC_GROUP_RAIL) {
1044  ClrBit(this->sel, scheme);
1045  }
1046  }
1047  }
1048 
1049  if (!current_class_valid) {
1050  Point pt = {0, 0};
1051  this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1052  }
1053  }
1054 };
1055 
1056 static const NWidgetPart _nested_select_company_livery_widgets [] = {
1058  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1059  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1060  EndContainer(),
1062  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1063  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1064  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1065  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1066  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1067  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_TOOLTIP),
1068  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),
1069  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_TOOLTIP),
1070  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_TOOLTIP),
1071  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(),
1072  EndContainer(),
1074  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(),
1075  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_BLACK_STRING, STR_LIVERY_PRIMARY_TOOLTIP),
1076  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1),
1077  SetDataTip(STR_BLACK_STRING, STR_LIVERY_SECONDARY_TOOLTIP),
1078  EndContainer(),
1080  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),
1083  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1084  EndContainer(),
1085  EndContainer(),
1086 };
1087 
1088 static WindowDesc _select_company_livery_desc(
1089  WDP_AUTO, "company_livery", 0, 0,
1091  0,
1092  _nested_select_company_livery_widgets, lengthof(_nested_select_company_livery_widgets)
1093 );
1094 
1095 void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1096 {
1098  if (w == nullptr) {
1099  new SelectCompanyLiveryWindow(&_select_company_livery_desc, company, group);
1100  } else if (group != INVALID_GROUP) {
1101  w->SetSelectedGroup(company, group);
1102  }
1103 }
1104 
1112 void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
1113 {
1115 
1116  bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1117  bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1118  bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1119  PaletteID pal;
1120 
1121  /* Modify eye colour palette only if 2 or more valid values exist */
1122  if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1123  pal = PAL_NONE;
1124  } else {
1125  switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1126  default: NOT_REACHED();
1127  case 0: pal = PALETTE_TO_BROWN; break;
1128  case 1: pal = PALETTE_TO_BLUE; break;
1129  case 2: pal = PALETTE_TO_GREEN; break;
1130  }
1131  }
1132 
1133  /* Draw the gradient (background) */
1134  DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1135 
1136  for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1137  switch (cmfv) {
1138  case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1139  case CMFV_LIPS:
1140  case CMFV_NOSE: if (has_moustache) continue; break;
1141  case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1142  case CMFV_GLASSES: if (!has_glasses) continue; break;
1143  default: break;
1144  }
1145  DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1146  }
1147 }
1148 
1152  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1153  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1154  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP),
1155  EndContainer(),
1156  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1158  NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
1161  NWidget(NWID_SPACER), SetFill(1, 0),
1162  NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCMF_FACE), SetMinimalSize(92, 119),
1163  NWidget(NWID_SPACER), SetFill(1, 0),
1164  EndContainer(),
1166  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetDataTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1167  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1169  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1170  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetDataTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1171  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetDataTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1172  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetDataTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1173  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1174  EndContainer(),
1175  EndContainer(),
1176  EndContainer(),
1178  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1180  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1182  NWidget(NWID_SPACER), SetFill(0, 1),
1183  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1184  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1185  NWidget(NWID_SPACER), SetFill(0, 1),
1186  EndContainer(),
1187  EndContainer(),
1188  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1192  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1193  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1194  EndContainer(),
1197  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
1198  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
1199  EndContainer(),
1203  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
1204  EndContainer(),
1206  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1207  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
1208  EndContainer(),
1209  NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
1211  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1212  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1213  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
1214  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1215  EndContainer(),
1217  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1218  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1219  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
1220  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1221  EndContainer(),
1223  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1224  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1225  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
1226  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1227  EndContainer(),
1229  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1230  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1231  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
1232  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1233  EndContainer(),
1235  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1236  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1237  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
1238  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1239  EndContainer(),
1241  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1242  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1243  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1244  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1245  EndContainer(),
1247  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1248  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1249  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
1250  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1251  EndContainer(),
1253  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1254  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1255  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
1256  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1257  EndContainer(),
1259  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1260  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1261  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
1262  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1263  EndContainer(),
1265  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1266  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1267  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
1268  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1269  EndContainer(),
1270  NWidget(NWID_SPACER), SetFill(0, 1),
1271  EndContainer(),
1272  EndContainer(),
1273  EndContainer(),
1274  EndContainer(),
1276  EndContainer(),
1278  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1279  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1280  EndContainer(),
1281 };
1282 
1285 {
1287  bool advanced;
1288 
1290  bool is_female;
1292 
1295 
1296  static const StringID PART_TEXTS_IS_FEMALE[];
1297  static const StringID PART_TEXTS[];
1298 
1306  void DrawFaceStringLabel(byte widget_index, uint8 val, bool is_bool_widget) const
1307  {
1308  StringID str;
1309  const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1310  if (!nwi_widget->IsDisabled()) {
1311  if (is_bool_widget) {
1312  /* if it a bool button write yes or no */
1313  str = (val != 0) ? STR_FACE_YES : STR_FACE_NO;
1314  } else {
1315  /* else write the value + 1 */
1316  SetDParam(0, val + 1);
1317  str = STR_JUST_INT;
1318  }
1319 
1320  /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
1321  DrawString(nwi_widget->pos_x + nwi_widget->IsLowered(), nwi_widget->pos_x + nwi_widget->current_x - 1 - nwi_widget->IsLowered(),
1322  nwi_widget->pos_y + 1 + nwi_widget->IsLowered(), str, TC_WHITE, SA_HOR_CENTER);
1323  }
1324  }
1325 
1326  void UpdateData()
1327  {
1328  this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1329  this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1330  this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1331  }
1332 
1333 public:
1334  SelectCompanyManagerFaceWindow(WindowDesc *desc, Window *parent) : Window(desc)
1335  {
1336  this->advanced = false;
1337  this->CreateNestedTree();
1338  this->SelectDisplayPlanes(this->advanced);
1339  this->FinishInitNested(parent->window_number);
1340  this->parent = parent;
1341  this->owner = (Owner)this->window_number;
1342  this->face = Company::Get((CompanyID)this->window_number)->face;
1343 
1344  this->UpdateData();
1345  }
1346 
1351  void SelectDisplayPlanes(bool advanced)
1352  {
1353  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1354  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1355  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1356  this->GetWidget<NWidgetCore>(WID_SCMF_RANDOM_NEW_FACE)->widget_data = advanced ? STR_FACE_RANDOM : STR_FACE_NEW_FACE_BUTTON;
1357 
1358  NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1359  if (advanced) {
1360  wi->SetDataTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1361  } else {
1362  wi->SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1363  }
1364  }
1365 
1366  void OnInit() override
1367  {
1368  /* Size of the boolean yes/no button. */
1369  Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
1370  yesno_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1371  yesno_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1372  /* Size of the number button + arrows. */
1373  Dimension number_dim = {0, 0};
1374  for (int val = 1; val <= 12; val++) {
1375  SetDParam(0, val);
1376  number_dim = maxdim(number_dim, GetStringBoundingBox(STR_JUST_INT));
1377  }
1378  uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT);
1379  number_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + arrows_width;
1380  number_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1381  /* Compute width of both buttons. */
1382  yesno_dim.width = max(yesno_dim.width, number_dim.width);
1383  number_dim.width = yesno_dim.width - arrows_width;
1384 
1385  this->yesno_dim = yesno_dim;
1386  this->number_dim = number_dim;
1387  }
1388 
1389  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1390  {
1391  switch (widget) {
1392  case WID_SCMF_FACE: {
1393  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
1394  size->width = max(size->width, face_size.width);
1395  size->height = max(size->height, face_size.height);
1396  break;
1397  }
1398 
1401  int offset = (widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2;
1402  *size = maxdim(GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset]), GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset + 1]));
1403  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1404  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1405  break;
1406  }
1407 
1409  *size = maxdim(GetStringBoundingBox(STR_FACE_LIPS), GetStringBoundingBox(STR_FACE_MOUSTACHE));
1410  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1411  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1412  break;
1413 
1415  case WID_SCMF_HAIR_TEXT:
1418  case WID_SCMF_GLASSES_TEXT:
1419  case WID_SCMF_NOSE_TEXT:
1420  case WID_SCMF_CHIN_TEXT:
1421  case WID_SCMF_JACKET_TEXT:
1422  case WID_SCMF_COLLAR_TEXT:
1423  *size = GetStringBoundingBox(PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT]);
1424  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1425  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1426  break;
1427 
1429  case WID_SCMF_HAS_GLASSES:
1430  *size = this->yesno_dim;
1431  break;
1432 
1433  case WID_SCMF_EYECOLOUR:
1434  case WID_SCMF_CHIN:
1435  case WID_SCMF_EYEBROWS:
1437  case WID_SCMF_NOSE:
1438  case WID_SCMF_HAIR:
1439  case WID_SCMF_JACKET:
1440  case WID_SCMF_COLLAR:
1441  case WID_SCMF_TIE_EARRING:
1442  case WID_SCMF_GLASSES:
1443  *size = this->number_dim;
1444  break;
1445  }
1446  }
1447 
1448  void OnPaint() override
1449  {
1450  /* lower the non-selected gender button */
1451  this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2, WIDGET_LIST_END);
1452  this->SetWidgetsLoweredState( this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2, WIDGET_LIST_END);
1453 
1454  /* advanced company manager face selection window */
1455 
1456  /* lower the non-selected ethnicity button */
1457  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
1458  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
1459 
1460 
1461  /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1462  * (or in other words you haven't any choice).
1463  * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1464 
1465  /* Eye colour buttons */
1466  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1468 
1469  /* Chin buttons */
1470  this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1472 
1473  /* Eyebrows buttons */
1474  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1476 
1477  /* Lips or (if it a male face with a moustache) moustache buttons */
1478  this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1480 
1481  /* Nose buttons | male faces with moustache haven't any nose options */
1482  this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1484 
1485  /* Hair buttons */
1486  this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1488 
1489  /* Jacket buttons */
1490  this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1492 
1493  /* Collar buttons */
1494  this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1496 
1497  /* Tie/earring buttons | female faces without earring haven't any earring options */
1498  this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1499  (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1501 
1502  /* Glasses buttons | faces without glasses haven't any glasses options */
1503  this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1505 
1506  this->DrawWidgets();
1507  }
1508 
1509  void DrawWidget(const Rect &r, int widget) const override
1510  {
1511  switch (widget) {
1514  StringID str = PART_TEXTS_IS_FEMALE[(widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2 + this->is_female];
1515  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_GOLD, SA_RIGHT);
1516  break;
1517  }
1518 
1520  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);
1521  break;
1522 
1524  case WID_SCMF_HAIR_TEXT:
1527  case WID_SCMF_GLASSES_TEXT:
1528  case WID_SCMF_NOSE_TEXT:
1529  case WID_SCMF_CHIN_TEXT:
1530  case WID_SCMF_JACKET_TEXT:
1531  case WID_SCMF_COLLAR_TEXT:
1532  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);
1533  break;
1534 
1535 
1537  if (this->is_female) { // Only for female faces
1538  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true);
1539  } else { // Only for male faces
1540  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge), true);
1541  }
1542  break;
1543 
1544  case WID_SCMF_TIE_EARRING:
1545  this->DrawFaceStringLabel(WID_SCMF_TIE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1546  break;
1547 
1549  if (this->is_moust_male) { // Only for male faces with moustache
1550  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_MOUSTACHE, this->ge), false);
1551  } else { // Only for female faces or male faces without moustache
1552  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_LIPS, this->ge), false);
1553  }
1554  break;
1555 
1556  case WID_SCMF_HAS_GLASSES:
1557  this->DrawFaceStringLabel(WID_SCMF_HAS_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1558  break;
1559 
1560  case WID_SCMF_HAIR:
1561  this->DrawFaceStringLabel(WID_SCMF_HAIR, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1562  break;
1563 
1564  case WID_SCMF_EYEBROWS:
1565  this->DrawFaceStringLabel(WID_SCMF_EYEBROWS, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1566  break;
1567 
1568  case WID_SCMF_EYECOLOUR:
1569  this->DrawFaceStringLabel(WID_SCMF_EYECOLOUR, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1570  break;
1571 
1572  case WID_SCMF_GLASSES:
1573  this->DrawFaceStringLabel(WID_SCMF_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1574  break;
1575 
1576  case WID_SCMF_NOSE:
1577  this->DrawFaceStringLabel(WID_SCMF_NOSE, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1578  break;
1579 
1580  case WID_SCMF_CHIN:
1581  this->DrawFaceStringLabel(WID_SCMF_CHIN, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1582  break;
1583 
1584  case WID_SCMF_JACKET:
1585  this->DrawFaceStringLabel(WID_SCMF_JACKET, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1586  break;
1587 
1588  case WID_SCMF_COLLAR:
1589  this->DrawFaceStringLabel(WID_SCMF_COLLAR, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1590  break;
1591 
1592  case WID_SCMF_FACE:
1593  DrawCompanyManagerFace(this->face, Company::Get((CompanyID)this->window_number)->colour, r.left, r.top);
1594  break;
1595  }
1596  }
1597 
1598  void OnClick(Point pt, int widget, int click_count) override
1599  {
1600  switch (widget) {
1601  /* Toggle size, advanced/simple face selection */
1604  this->advanced = !this->advanced;
1605  this->SelectDisplayPlanes(this->advanced);
1606  this->ReInit();
1607  break;
1608 
1609  /* OK button */
1610  case WID_SCMF_ACCEPT:
1611  DoCommandP(0, 0, this->face, CMD_SET_COMPANY_MANAGER_FACE);
1612  FALLTHROUGH;
1613 
1614  /* Cancel button */
1615  case WID_SCMF_CANCEL:
1616  delete this;
1617  break;
1618 
1619  /* Load button */
1620  case WID_SCMF_LOAD:
1621  this->face = _company_manager_face;
1622  ScaleAllCompanyManagerFaceBits(this->face);
1623  ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, WL_INFO);
1624  this->UpdateData();
1625  this->SetDirty();
1626  break;
1627 
1628  /* 'Company manager face number' button, view and/or set company manager face number */
1629  case WID_SCMF_FACECODE:
1630  SetDParam(0, this->face);
1631  ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, this, CS_NUMERAL, QSF_NONE);
1632  break;
1633 
1634  /* Save button */
1635  case WID_SCMF_SAVE:
1636  _company_manager_face = this->face;
1637  ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, WL_INFO);
1638  break;
1639 
1640  /* Toggle gender (male/female) button */
1641  case WID_SCMF_MALE:
1642  case WID_SCMF_FEMALE:
1643  case WID_SCMF_MALE2:
1644  case WID_SCMF_FEMALE2:
1645  SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1646  ScaleAllCompanyManagerFaceBits(this->face);
1647  this->UpdateData();
1648  this->SetDirty();
1649  break;
1650 
1651  /* Randomize face button */
1653  RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced);
1654  this->UpdateData();
1655  this->SetDirty();
1656  break;
1657 
1658  /* Toggle ethnicity (european/african) button */
1661  SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1662  ScaleAllCompanyManagerFaceBits(this->face);
1663  this->UpdateData();
1664  this->SetDirty();
1665  break;
1666 
1667  default:
1668  /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1669  * First it checks which CompanyManagerFaceVariable is being changed, and then either
1670  * a: invert the value for boolean variables, or
1671  * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1672  if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1673  CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1674 
1675  if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1676  switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1677  default: NOT_REACHED();
1678  case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1679  case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1680  }
1681  SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1682  ScaleAllCompanyManagerFaceBits(this->face);
1683  } else { // Value buttons
1684  switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1685  default: NOT_REACHED();
1686  case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1687  case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1688  case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1689  case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1690  case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1691  case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1692  case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1693  case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1694  case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1695  case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1696  }
1697  /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1698  IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1699  }
1700  this->UpdateData();
1701  this->SetDirty();
1702  }
1703  break;
1704  }
1705  }
1706 
1707  void OnQueryTextFinished(char *str) override
1708  {
1709  if (str == nullptr) return;
1710  /* Set a new company manager face number */
1711  if (!StrEmpty(str)) {
1712  this->face = strtoul(str, nullptr, 10);
1713  ScaleAllCompanyManagerFaceBits(this->face);
1714  ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, WL_INFO);
1715  this->UpdateData();
1716  this->SetDirty();
1717  } else {
1718  ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, WL_INFO);
1719  }
1720  }
1721 };
1722 
1725  STR_FACE_MOUSTACHE, STR_FACE_EARRING, // WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
1726  STR_FACE_TIE, STR_FACE_EARRING, // WID_SCMF_TIE_EARRING_TEXT
1727 };
1728 
1731  STR_FACE_GLASSES, // WID_SCMF_HAS_GLASSES_TEXT
1732  STR_FACE_HAIR, // WID_SCMF_HAIR_TEXT
1733  STR_FACE_EYEBROWS, // WID_SCMF_EYEBROWS_TEXT
1734  STR_FACE_EYECOLOUR, // WID_SCMF_EYECOLOUR_TEXT
1735  STR_FACE_GLASSES, // WID_SCMF_GLASSES_TEXT
1736  STR_FACE_NOSE, // WID_SCMF_NOSE_TEXT
1737  STR_FACE_CHIN, // WID_SCMF_CHIN_TEXT
1738  STR_FACE_JACKET, // WID_SCMF_JACKET_TEXT
1739  STR_FACE_COLLAR, // WID_SCMF_COLLAR_TEXT
1740 };
1741 
1744  WDP_AUTO, "company_face", 0, 0,
1747  _nested_select_company_manager_face_widgets, lengthof(_nested_select_company_manager_face_widgets)
1748 );
1749 
1756 {
1757  if (!Company::IsValidID((CompanyID)parent->window_number)) return;
1758 
1760  new SelectCompanyManagerFaceWindow(&_select_company_manager_face_desc, parent);
1761 }
1762 
1763 static const NWidgetPart _nested_company_infrastructure_widgets[] = {
1765  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1766  NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), SetDataTip(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1767  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1768  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1769  EndContainer(),
1770  NWidget(WWT_PANEL, COLOUR_GREY),
1772  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1773  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1774  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1775  EndContainer(),
1776  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1777  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1778  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1779  EndContainer(),
1780  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1781  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1782  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TRAM_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1783  EndContainer(),
1784  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1785  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1786  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1787  EndContainer(),
1788  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1789  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1790  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1791  EndContainer(),
1792  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1793  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
1794  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
1795  EndContainer(),
1796  EndContainer(),
1797  EndContainer(),
1798 };
1799 
1804 {
1807 
1809 
1810  CompanyInfrastructureWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
1811  {
1812  this->UpdateRailRoadTypes();
1813 
1814  this->InitNested(window_number);
1815  this->owner = (Owner)this->window_number;
1816  }
1817 
1818  void UpdateRailRoadTypes()
1819  {
1820  this->railtypes = RAILTYPES_NONE;
1821  this->roadtypes = ROADTYPES_NONE;
1822 
1823  /* Find the used railtypes. */
1824  for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
1825  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1826 
1827  this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1828  }
1829 
1830  /* Get the date introduced railtypes as well. */
1831  this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY);
1832 
1833  /* Find the used roadtypes. */
1834  for (const Engine *e : Engine::IterateType(VEH_ROAD)) {
1835  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1836 
1837  this->roadtypes |= GetRoadTypeInfo(e->u.road.roadtype)->introduces_roadtypes;
1838  }
1839 
1840  /* Get the date introduced roadtypes as well. */
1841  this->roadtypes = AddDateIntroducedRoadTypes(this->roadtypes, MAX_DAY);
1842  this->roadtypes &= ~_roadtypes_hidden_mask;
1843  }
1844 
1847  {
1848  const Company *c = Company::Get((CompanyID)this->window_number);
1849  Money total;
1850 
1851  uint32 rail_total = c->infrastructure.GetRailTotal();
1852  for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1853  if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1854  }
1856 
1857  uint32 road_total = c->infrastructure.GetRoadTotal();
1858  uint32 tram_total = c->infrastructure.GetTramTotal();
1859  for (RoadType rt = ROADTYPE_BEGIN; rt != ROADTYPE_END; rt++) {
1860  if (HasBit(this->roadtypes, rt)) total += RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total);
1861  }
1862 
1865  total += AirportMaintenanceCost(c->index);
1866 
1867  return total;
1868  }
1869 
1870  void SetStringParameters(int widget) const override
1871  {
1872  switch (widget) {
1873  case WID_CI_CAPTION:
1874  SetDParam(0, (CompanyID)this->window_number);
1875  break;
1876  }
1877  }
1878 
1879  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
1880  {
1881  const Company *c = Company::Get((CompanyID)this->window_number);
1882 
1883  switch (widget) {
1884  case WID_CI_RAIL_DESC: {
1885  uint lines = 1; // Starts at 1 because a line is also required for the section title
1886 
1887  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width);
1888 
1889  RailType rt;
1891  if (HasBit(this->railtypes, rt)) {
1892  lines++;
1893  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
1894  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1895  }
1896  }
1897  if (this->railtypes != RAILTYPES_NONE) {
1898  lines++;
1899  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + WD_FRAMERECT_LEFT);
1900  }
1901 
1902  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1903  break;
1904  }
1905 
1906  case WID_CI_ROAD_DESC:
1907  case WID_CI_TRAM_DESC: {
1908  uint lines = 1; // Starts at 1 because a line is also required for the section title
1909 
1910  size->width = max(size->width, GetStringBoundingBox(widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT).width);
1911 
1912  RoadType rt;
1914  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
1915  lines++;
1916  SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
1917  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1918  }
1919  }
1920 
1921  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1922  break;
1923  }
1924 
1925  case WID_CI_WATER_DESC:
1926  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width);
1927  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + WD_FRAMERECT_LEFT);
1928  break;
1929 
1930  case WID_CI_STATION_DESC:
1931  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width);
1932  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + WD_FRAMERECT_LEFT);
1933  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + WD_FRAMERECT_LEFT);
1934  break;
1935 
1936  case WID_CI_RAIL_COUNT:
1937  case WID_CI_ROAD_COUNT:
1938  case WID_CI_TRAM_COUNT:
1939  case WID_CI_WATER_COUNT:
1940  case WID_CI_STATION_COUNT:
1941  case WID_CI_TOTAL: {
1942  /* Find the maximum count that is displayed. */
1943  uint32 max_val = 1000; // Some random number to reserve enough space.
1944  Money max_cost = 10000; // Some random number to reserve enough space.
1945  uint32 rail_total = c->infrastructure.GetRailTotal();
1946  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1947  max_val = max(max_val, c->infrastructure.rail[rt]);
1948  max_cost = max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1949  }
1950  max_val = max(max_val, c->infrastructure.signal);
1951  max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1952  uint32 road_total = c->infrastructure.GetRoadTotal();
1953  uint32 tram_total = c->infrastructure.GetTramTotal();
1954  for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1955  max_val = max(max_val, c->infrastructure.road[rt]);
1956  max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt], RoadTypeIsRoad(rt) ? road_total : tram_total));
1957 
1958  }
1959  max_val = max(max_val, c->infrastructure.water);
1960  max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1961  max_val = max(max_val, c->infrastructure.station);
1962  max_cost = max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1963  max_val = max(max_val, c->infrastructure.airport);
1964  max_cost = max(max_cost, AirportMaintenanceCost(c->index));
1965 
1966  SetDParamMaxValue(0, max_val);
1967  uint count_width = GetStringBoundingBox(STR_WHITE_COMMA).width + 20; // Reserve some wiggle room
1968 
1970  SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1971  this->total_width = GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width + 20;
1972  size->width = max(size->width, this->total_width);
1973 
1974  SetDParamMaxValue(0, max_cost * 12); // Convert to per year
1975  count_width += max(this->total_width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width);
1976  }
1977 
1978  size->width = max(size->width, count_width);
1979 
1980  /* Set height of the total line. */
1981  if (widget == WID_CI_TOTAL) {
1983  }
1984  break;
1985  }
1986  }
1987  }
1988 
1996  void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1997  {
1998  SetDParam(0, count);
1999  DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA, TC_FROMSTRING, SA_RIGHT);
2000 
2002  SetDParam(0, monthly_cost * 12); // Convert to per year
2003  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
2004  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
2005  }
2006  }
2007 
2008  void DrawWidget(const Rect &r, int widget) const override
2009  {
2010  const Company *c = Company::Get((CompanyID)this->window_number);
2011  int y = r.top;
2012 
2013  int offs_left = _current_text_dir == TD_LTR ? WD_FRAMERECT_LEFT : 0;
2014  int offs_right = _current_text_dir == TD_LTR ? 0 : WD_FRAMERECT_LEFT;
2015 
2016  switch (widget) {
2017  case WID_CI_RAIL_DESC:
2018  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
2019 
2020  if (this->railtypes != RAILTYPES_NONE) {
2021  /* Draw name of each valid railtype. */
2022  RailType rt;
2024  if (HasBit(this->railtypes, rt)) {
2025  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
2026  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
2027  }
2028  }
2029  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
2030  } else {
2031  /* No valid railtype. */
2032  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2033  }
2034 
2035  break;
2036 
2037  case WID_CI_RAIL_COUNT: {
2038  /* Draw infrastructure count for each valid railtype. */
2039  uint32 rail_total = c->infrastructure.GetRailTotal();
2040  RailType rt;
2042  if (HasBit(this->railtypes, rt)) {
2043  this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
2044  }
2045  }
2046  if (this->railtypes != RAILTYPES_NONE) {
2047  this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
2048  }
2049  break;
2050  }
2051 
2052  case WID_CI_ROAD_DESC:
2053  case WID_CI_TRAM_DESC: {
2054  DrawString(r.left, r.right, y, widget == WID_CI_ROAD_DESC ? STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT : STR_COMPANY_INFRASTRUCTURE_VIEW_TRAM_SECT);
2055 
2056  /* Draw name of each valid roadtype. */
2057  RoadType rt;
2059  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_DESC)) {
2060  SetDParam(0, GetRoadTypeInfo(rt)->strings.name);
2061  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
2062  }
2063  }
2064 
2065  break;
2066  }
2067 
2068  case WID_CI_ROAD_COUNT:
2069  case WID_CI_TRAM_COUNT: {
2070  uint32 road_tram_total = widget == WID_CI_ROAD_COUNT ? c->infrastructure.GetRoadTotal() : c->infrastructure.GetTramTotal();
2071  RoadType rt;
2073  if (HasBit(this->roadtypes, rt) && RoadTypeIsRoad(rt) == (widget == WID_CI_ROAD_COUNT)) {
2074  this->DrawCountLine(r, y, c->infrastructure.road[rt], RoadMaintenanceCost(rt, c->infrastructure.road[rt], road_tram_total));
2075  }
2076  }
2077  break;
2078  }
2079 
2080  case WID_CI_WATER_DESC:
2081  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
2082  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
2083  break;
2084 
2085  case WID_CI_WATER_COUNT:
2086  this->DrawCountLine(r, y, c->infrastructure.water, CanalMaintenanceCost(c->infrastructure.water));
2087  break;
2088 
2089  case WID_CI_TOTAL:
2091  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
2092  GfxFillRect(left, y, left + this->total_width, y, PC_WHITE);
2093  y += EXP_LINESPACE;
2094  SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
2095  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
2096  }
2097  break;
2098 
2099  case WID_CI_STATION_DESC:
2100  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
2101  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
2102  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
2103  break;
2104 
2105  case WID_CI_STATION_COUNT:
2106  this->DrawCountLine(r, y, c->infrastructure.station, StationMaintenanceCost(c->infrastructure.station));
2107  this->DrawCountLine(r, y, c->infrastructure.airport, AirportMaintenanceCost(c->index));
2108  break;
2109  }
2110  }
2111 
2117  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2118  {
2119  if (!gui_scope) return;
2120 
2121  this->UpdateRailRoadTypes();
2122  this->ReInit();
2123  }
2124 };
2125 
2126 static WindowDesc _company_infrastructure_desc(
2127  WDP_AUTO, "company_infrastructure", 0, 0,
2129  0,
2130  _nested_company_infrastructure_widgets, lengthof(_nested_company_infrastructure_widgets)
2131 );
2132 
2138 {
2139  if (!Company::IsValidID(company)) return;
2140  AllocateWindowDescFront<CompanyInfrastructureWindow>(&_company_infrastructure_desc, company);
2141 }
2142 
2143 static const NWidgetPart _nested_company_widgets[] = {
2145  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2146  NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), SetDataTip(STR_COMPANY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2147  NWidget(WWT_SHADEBOX, COLOUR_GREY),
2148  NWidget(WWT_STICKYBOX, COLOUR_GREY),
2149  EndContainer(),
2150  NWidget(WWT_PANEL, COLOUR_GREY),
2151  NWidget(NWID_HORIZONTAL), SetPIP(4, 6, 4),
2152  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2153  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2154  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2155  EndContainer(),
2158  NWidget(NWID_VERTICAL), SetPIP(4, 5, 5),
2159  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INAUGURATION), SetDataTip(STR_COMPANY_VIEW_INAUGURATED_TITLE, STR_NULL), SetFill(1, 0),
2160  NWidget(NWID_HORIZONTAL), SetPIP(0, 5, 0),
2161  NWidget(WWT_LABEL, COLOUR_GREY, WID_C_DESC_COLOUR_SCHEME), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE, STR_NULL),
2162  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME_EXAMPLE), SetMinimalSize(30, 0), SetFill(0, 1),
2163  NWidget(NWID_SPACER), SetFill(1, 0),
2164  EndContainer(),
2165  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2167  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_VEHICLE), SetDataTip(STR_COMPANY_VIEW_VEHICLES_TITLE, STR_NULL),
2168  NWidget(NWID_SPACER), SetFill(0, 1),
2169  EndContainer(),
2171  NWidget(NWID_SPACER), SetFill(1, 0),
2172  EndContainer(),
2173  EndContainer(),
2174  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2176  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),
2177  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),
2178  EndContainer(),
2179  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_RELOCATE),
2180  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
2182  EndContainer(),
2183  NWidget(NWID_SPACER), SetFill(0, 1),
2184  EndContainer(),
2185  EndContainer(),
2186  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_COMPANY_VALUE), SetDataTip(STR_COMPANY_VIEW_COMPANY_VALUE, STR_NULL), SetFill(1, 0),
2187  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2188  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2190  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE, STR_NULL),
2191  NWidget(NWID_SPACER), SetFill(0, 1),
2192  EndContainer(),
2195  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2196  NWidget(NWID_SPACER), SetFill(0, 1), SetMinimalSize(90, 0),
2197  EndContainer(),
2198  EndContainer(),
2199  EndContainer(),
2202  NWidget(NWID_VERTICAL), SetPIP(5, 5, 4),
2203  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_OWNERS), SetMinimalTextLines(3, 0),
2204  NWidget(NWID_SPACER), SetFill(0, 1),
2205  EndContainer(),
2206  EndContainer(),
2207  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2208  NWidget(NWID_SPACER), SetMinimalSize(90, 0), SetFill(0, 1),
2209  /* Multi player buttons. */
2211  NWidget(WWT_EMPTY, COLOUR_GREY, WID_C_HAS_PASSWORD),
2213  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_PASSWORD), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_COMPANY_VIEW_PASSWORD_TOOLTIP),
2214  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2215  EndContainer(),
2216  EndContainer(),
2217  EndContainer(),
2218  EndContainer(),
2219  EndContainer(),
2220  EndContainer(),
2221  EndContainer(),
2222  /* Button bars at the bottom. */
2223  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_BUTTONS),
2225  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),
2226  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),
2227  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),
2228  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),
2229  EndContainer(),
2231  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),
2232  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),
2233  EndContainer(),
2234  EndContainer(),
2235 };
2236 
2237 int GetAmountOwnedBy(const Company *c, Owner owner)
2238 {
2239  return (c->share_owners[0] == owner) +
2240  (c->share_owners[1] == owner) +
2241  (c->share_owners[2] == owner) +
2242  (c->share_owners[3] == owner);
2243 }
2244 
2247  STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2248 };
2249 
2254 {
2255  CompanyWidgets query_widget;
2256 
2259  /* Display planes of the #WID_C_SELECT_MULTIPLAYER selection widget. */
2260  CWP_MP_C_PWD = 0,
2262 
2263  /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2264  CWP_VB_VIEW = 0,
2266 
2267  /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2268  CWP_RELOCATE_SHOW = 0,
2270 
2271  /* Display planes of the #WID_C_SELECT_BUTTONS selection widget. */
2272  CWP_BUTTONS_LOCAL = 0,
2274  };
2275 
2276  CompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2277  {
2278  this->InitNested(window_number);
2279  this->owner = (Owner)this->window_number;
2280  this->OnInvalidateData();
2281  }
2282 
2283  void OnPaint() override
2284  {
2285  const Company *c = Company::Get((CompanyID)this->window_number);
2286  bool local = this->window_number == _local_company;
2287 
2288  if (!this->IsShaded()) {
2289  bool reinit = false;
2290 
2291  /* Button bar selection. */
2292  int plane = local ? CWP_BUTTONS_LOCAL : CWP_BUTTONS_OTHER;
2293  NWidgetStacked *wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS);
2294  if (plane != wi->shown_plane) {
2295  wi->SetDisplayedPlane(plane);
2296  this->InvalidateData();
2297  return;
2298  }
2299 
2300  /* Build HQ button handling. */
2301  plane = (local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW;
2302  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ);
2303  if (plane != wi->shown_plane) {
2304  wi->SetDisplayedPlane(plane);
2305  this->SetDirty();
2306  return;
2307  }
2308 
2309  this->SetWidgetDisabledState(WID_C_VIEW_HQ, c->location_of_HQ == INVALID_TILE);
2310 
2311  /* Enable/disable 'Relocate HQ' button. */
2312  plane = (!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW;
2313  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE);
2314  if (plane != wi->shown_plane) {
2315  wi->SetDisplayedPlane(plane);
2316  this->SetDirty();
2317  return;
2318  }
2319 
2320  /* Owners of company */
2321  plane = SZSP_HORIZONTAL;
2322  for (uint i = 0; i < lengthof(c->share_owners); i++) {
2323  if (c->share_owners[i] != INVALID_COMPANY) {
2324  plane = 0;
2325  break;
2326  }
2327  }
2328  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_DESC_OWNERS);
2329  if (plane != wi->shown_plane) {
2330  wi->SetDisplayedPlane(plane);
2331  reinit = true;
2332  }
2333 
2334  /* Multiplayer buttons. */
2335  plane = ((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN));
2336  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER);
2337  if (plane != wi->shown_plane) {
2338  wi->SetDisplayedPlane(plane);
2339  reinit = true;
2340  }
2341  this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
2342 
2343  if (reinit) {
2344  this->ReInit();
2345  return;
2346  }
2347  }
2348 
2349  this->DrawWidgets();
2350  }
2351 
2352  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2353  {
2354  switch (widget) {
2355  case WID_C_FACE: {
2356  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
2357  size->width = max(size->width, face_size.width);
2358  size->height = max(size->height, face_size.height);
2359  break;
2360  }
2361 
2363  Point offset;
2364  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2365  d.width -= offset.x;
2366  d.height -= offset.y;
2367  *size = maxdim(*size, d);
2368  break;
2369  }
2370 
2372  SetDParam(0, INT64_MAX); // Arguably the maximum company value
2373  size->width = GetStringBoundingBox(STR_COMPANY_VIEW_COMPANY_VALUE).width;
2374  break;
2375 
2377  SetDParamMaxValue(0, 5000); // Maximum number of vehicles
2378  for (uint i = 0; i < lengthof(_company_view_vehicle_count_strings); i++) {
2379  size->width = max(size->width, GetStringBoundingBox(_company_view_vehicle_count_strings[i]).width);
2380  }
2381  break;
2382 
2384  SetDParamMaxValue(0, UINT_MAX);
2385  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL).width);
2386  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD).width);
2387  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER).width);
2388  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION).width);
2389  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT).width);
2390  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE).width);
2391  break;
2392 
2393  case WID_C_DESC_OWNERS: {
2394  for (const Company *c2 : Company::Iterate()) {
2395  SetDParamMaxValue(0, 75);
2396  SetDParam(1, c2->index);
2397 
2398  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_SHARES_OWNED_BY).width);
2399  }
2400  break;
2401  }
2402 
2403  case WID_C_HAS_PASSWORD:
2404  *size = maxdim(*size, GetSpriteSize(SPR_LOCK));
2405  break;
2406  }
2407  }
2408 
2409  void DrawWidget(const Rect &r, int widget) const override
2410  {
2411  const Company *c = Company::Get((CompanyID)this->window_number);
2412  switch (widget) {
2413  case WID_C_FACE:
2414  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2415  break;
2416 
2417  case WID_C_FACE_TITLE:
2418  SetDParam(0, c->index);
2419  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
2420  break;
2421 
2423  Point offset;
2424  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2425  d.height -= offset.y;
2426  DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, (r.top + r.bottom - d.height) / 2 - offset.y);
2427  break;
2428  }
2429 
2431  uint amounts[4];
2432  amounts[0] = c->group_all[VEH_TRAIN].num_vehicle;
2433  amounts[1] = c->group_all[VEH_ROAD].num_vehicle;
2434  amounts[2] = c->group_all[VEH_SHIP].num_vehicle;
2435  amounts[3] = c->group_all[VEH_AIRCRAFT].num_vehicle;
2436 
2437  int y = r.top;
2438  if (amounts[0] + amounts[1] + amounts[2] + amounts[3] == 0) {
2439  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2440  } else {
2441  assert_compile(lengthof(amounts) == lengthof(_company_view_vehicle_count_strings));
2442 
2443  for (uint i = 0; i < lengthof(amounts); i++) {
2444  if (amounts[i] != 0) {
2445  SetDParam(0, amounts[i]);
2446  DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[i]);
2447  y += FONT_HEIGHT_NORMAL;
2448  }
2449  }
2450  }
2451  break;
2452  }
2453 
2455  uint y = r.top;
2456 
2457  /* Collect rail and road counts. */
2458  uint rail_pieces = c->infrastructure.signal;
2459  uint road_pieces = 0;
2460  for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pieces += c->infrastructure.rail[i];
2461  for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
2462 
2463  if (rail_pieces == 0 && road_pieces == 0 && c->infrastructure.water == 0 && c->infrastructure.station == 0 && c->infrastructure.airport == 0) {
2464  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2465  } else {
2466  if (rail_pieces != 0) {
2467  SetDParam(0, rail_pieces);
2468  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
2469  y += FONT_HEIGHT_NORMAL;
2470  }
2471  if (road_pieces != 0) {
2472  SetDParam(0, road_pieces);
2473  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
2474  y += FONT_HEIGHT_NORMAL;
2475  }
2476  if (c->infrastructure.water != 0) {
2478  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
2479  y += FONT_HEIGHT_NORMAL;
2480  }
2481  if (c->infrastructure.station != 0) {
2483  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
2484  y += FONT_HEIGHT_NORMAL;
2485  }
2486  if (c->infrastructure.airport != 0) {
2488  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
2489  }
2490  }
2491 
2492  break;
2493  }
2494 
2495  case WID_C_DESC_OWNERS: {
2496  uint y = r.top;
2497 
2498  for (const Company *c2 : Company::Iterate()) {
2499  uint amt = GetAmountOwnedBy(c, c2->index);
2500  if (amt != 0) {
2501  SetDParam(0, amt * 25);
2502  SetDParam(1, c2->index);
2503 
2504  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_SHARES_OWNED_BY);
2505  y += FONT_HEIGHT_NORMAL;
2506  }
2507  }
2508  break;
2509  }
2510 
2511  case WID_C_HAS_PASSWORD:
2513  DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top);
2514  }
2515  break;
2516  }
2517  }
2518 
2519  void SetStringParameters(int widget) const override
2520  {
2521  switch (widget) {
2522  case WID_C_CAPTION:
2523  SetDParam(0, (CompanyID)this->window_number);
2524  SetDParam(1, (CompanyID)this->window_number);
2525  break;
2526 
2528  SetDParam(0, Company::Get((CompanyID)this->window_number)->inaugurated_year);
2529  break;
2530 
2532  SetDParam(0, CalculateCompanyValue(Company::Get((CompanyID)this->window_number)));
2533  break;
2534  }
2535  }
2536 
2537  void OnClick(Point pt, int widget, int click_count) override
2538  {
2539  switch (widget) {
2540  case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2541 
2542  case WID_C_COLOUR_SCHEME:
2543  ShowCompanyLiveryWindow((CompanyID)this->window_number, INVALID_GROUP);
2544  break;
2545 
2546  case WID_C_PRESIDENT_NAME:
2547  this->query_widget = WID_C_PRESIDENT_NAME;
2548  SetDParam(0, this->window_number);
2549  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);
2550  break;
2551 
2552  case WID_C_COMPANY_NAME:
2553  this->query_widget = WID_C_COMPANY_NAME;
2554  SetDParam(0, this->window_number);
2555  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);
2556  break;
2557 
2558  case WID_C_VIEW_HQ: {
2559  TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
2560  if (_ctrl_pressed) {
2562  } else {
2563  ScrollMainWindowToTile(tile);
2564  }
2565  break;
2566  }
2567 
2568  case WID_C_BUILD_HQ:
2569  if ((byte)this->window_number != _local_company) return;
2570  if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2572  this->RaiseButtons();
2573  break;
2574  }
2575  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2576  SetTileSelectSize(2, 2);
2577  this->LowerWidget(WID_C_BUILD_HQ);
2578  this->SetWidgetDirty(WID_C_BUILD_HQ);
2579  break;
2580 
2581  case WID_C_RELOCATE_HQ:
2582  if (this->IsWidgetLowered(WID_C_RELOCATE_HQ)) {
2584  this->RaiseButtons();
2585  break;
2586  }
2587  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2588  SetTileSelectSize(2, 2);
2589  this->LowerWidget(WID_C_RELOCATE_HQ);
2590  this->SetWidgetDirty(WID_C_RELOCATE_HQ);
2591  break;
2592 
2594  ShowCompanyInfrastructure((CompanyID)this->window_number);
2595  break;
2596 
2597  case WID_C_BUY_SHARE:
2598  DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
2599  break;
2600 
2601  case WID_C_SELL_SHARE:
2602  DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
2603  break;
2604 
2606  if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
2607  break;
2608 
2609  case WID_C_COMPANY_JOIN: {
2610  this->query_widget = WID_C_COMPANY_JOIN;
2611  CompanyID company = (CompanyID)this->window_number;
2612  if (_network_server) {
2615  } else if (NetworkCompanyIsPassworded(company)) {
2616  /* ask for the password */
2617  ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, this, CS_ALPHANUMERAL, QSF_PASSWORD);
2618  } else {
2619  /* just send the join command */
2620  NetworkClientRequestMove(company);
2621  }
2622  break;
2623  }
2624  }
2625  }
2626 
2627  void OnHundredthTick() override
2628  {
2629  /* redraw the window every now and then */
2630  this->SetDirty();
2631  }
2632 
2633  void OnPlaceObject(Point pt, TileIndex tile) override
2634  {
2635  if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)) && !_shift_pressed) {
2637  this->RaiseButtons();
2638  }
2639  }
2640 
2641  void OnPlaceObjectAbort() override
2642  {
2643  this->RaiseButtons();
2644  }
2645 
2646  void OnQueryTextFinished(char *str) override
2647  {
2648  if (str == nullptr) return;
2649 
2650  switch (this->query_widget) {
2651  default: NOT_REACHED();
2652 
2653  case WID_C_PRESIDENT_NAME:
2654  DoCommandP(0, 0, 0, CMD_RENAME_PRESIDENT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_PRESIDENT), nullptr, str);
2655  break;
2656 
2657  case WID_C_COMPANY_NAME:
2658  DoCommandP(0, 0, 0, CMD_RENAME_COMPANY | CMD_MSG(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME), nullptr, str);
2659  break;
2660 
2661  case WID_C_COMPANY_JOIN:
2662  NetworkClientRequestMove((CompanyID)this->window_number, str);
2663  break;
2664  }
2665  }
2666 
2667 
2673  void OnInvalidateData(int data = 0, bool gui_scope = true) override
2674  {
2675  if (this->window_number == _local_company) return;
2676 
2677  if (_settings_game.economy.allow_shares) { // Shares are allowed
2678  const Company *c = Company::Get(this->window_number);
2679 
2680  /* If all shares are owned by someone (none by nobody), disable buy button */
2681  this->SetWidgetDisabledState(WID_C_BUY_SHARE, GetAmountOwnedBy(c, INVALID_OWNER) == 0 ||
2682  /* Only 25% left to buy. If the company is human, disable buying it up.. TODO issues! */
2683  (GetAmountOwnedBy(c, INVALID_OWNER) == 1 && !c->is_ai) ||
2684  /* Spectators cannot do anything of course */
2686 
2687  /* If the company doesn't own any shares, disable sell button */
2688  this->SetWidgetDisabledState(WID_C_SELL_SHARE, (GetAmountOwnedBy(c, _local_company) == 0) ||
2689  /* Spectators cannot do anything of course */
2691  } else { // Shares are not allowed, disable buy/sell buttons
2692  this->DisableWidget(WID_C_BUY_SHARE);
2693  this->DisableWidget(WID_C_SELL_SHARE);
2694  }
2695  }
2696 };
2697 
2698 static WindowDesc _company_desc(
2699  WDP_AUTO, "company", 0, 0,
2701  0,
2702  _nested_company_widgets, lengthof(_nested_company_widgets)
2703 );
2704 
2709 void ShowCompany(CompanyID company)
2710 {
2711  if (!Company::IsValidID(company)) return;
2712 
2713  AllocateWindowDescFront<CompanyWindow>(&_company_desc, company);
2714 }
2715 
2721 {
2722  SetWindowDirty(WC_COMPANY, company);
2724 }
2725 
2727  BuyCompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2728  {
2729  this->InitNested(window_number);
2730  }
2731 
2732  void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) override
2733  {
2734  switch (widget) {
2735  case WID_BC_FACE:
2736  *size = GetSpriteSize(SPR_GRADIENT);
2737  break;
2738 
2739  case WID_BC_QUESTION:
2740  const Company *c = Company::Get((CompanyID)this->window_number);
2741  SetDParam(0, c->index);
2742  SetDParam(1, c->bankrupt_value);
2743  size->height = GetStringHeight(STR_BUY_COMPANY_MESSAGE, size->width);
2744  break;
2745  }
2746  }
2747 
2748  void SetStringParameters(int widget) const override
2749  {
2750  switch (widget) {
2751  case WID_BC_CAPTION:
2752  SetDParam(0, STR_COMPANY_NAME);
2753  SetDParam(1, Company::Get((CompanyID)this->window_number)->index);
2754  break;
2755  }
2756  }
2757 
2758  void DrawWidget(const Rect &r, int widget) const override
2759  {
2760  switch (widget) {
2761  case WID_BC_FACE: {
2762  const Company *c = Company::Get((CompanyID)this->window_number);
2763  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2764  break;
2765  }
2766 
2767  case WID_BC_QUESTION: {
2768  const Company *c = Company::Get((CompanyID)this->window_number);
2769  SetDParam(0, c->index);
2770  SetDParam(1, c->bankrupt_value);
2771  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING, SA_CENTER);
2772  break;
2773  }
2774  }
2775  }
2776 
2777  void OnClick(Point pt, int widget, int click_count) override
2778  {
2779  switch (widget) {
2780  case WID_BC_NO:
2781  delete this;
2782  break;
2783 
2784  case WID_BC_YES:
2785  DoCommandP(0, this->window_number, 0, CMD_BUY_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_COMPANY));
2786  break;
2787  }
2788  }
2789 };
2790 
2791 static const NWidgetPart _nested_buy_company_widgets[] = {
2793  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2794  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2795  EndContainer(),
2796  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2797  NWidget(NWID_VERTICAL), SetPIP(8, 8, 8),
2798  NWidget(NWID_HORIZONTAL), SetPIP(8, 10, 8),
2799  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2800  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2801  EndContainer(),
2802  NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(100, 10, 100),
2803  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
2804  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
2805  EndContainer(),
2806  EndContainer(),
2807  EndContainer(),
2808 };
2809 
2810 static WindowDesc _buy_company_desc(
2811  WDP_AUTO, nullptr, 0, 0,
2814  _nested_buy_company_widgets, lengthof(_nested_buy_company_widgets)
2815 );
2816 
2822 {
2823  AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, company);
2824 }
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:80
Jacket right.
Collar left.
Definition of stuff that is very close to a company, like the company struct itself.
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition: engine_base.h:157
#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:207
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:3218
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:329
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:1121
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:326
Description of road.
buy a company which is bankrupt
Definition: command_type.h:259
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:227
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:685
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:25
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
bool Sort(Comp compare)
Sort the list.
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:177
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:79
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:652
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:245
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:636
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:536
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.
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:204
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:838
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:378
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:64
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:78
sell a share from a company
Definition: command_type.h:258
Class general.
TextDirection _current_text_dir
Text direction of the currently selected language.
Definition: strings.cpp: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:246
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:97
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:908
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:318
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:370
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:711
GameCreationSettings game_creation
settings used during the creation of a game (map)
buy a share from a company
Definition: command_type.h:257
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:81
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:1262
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:973
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:1600
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:759
(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.