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