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