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(group);
711  }
712 
713  this->FinishInitNested(company);
714  this->owner = company;
715  this->InvalidateData(1);
716  }
717 
718  void SetSelectedGroup(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((CompanyID)this->window_number);
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  if (!Group::IsValidID(this->sel)) this->sel = INVALID_GROUP;
1029  this->groups.ForceRebuild();
1030  this->BuildGroupList((CompanyID)this->window_number);
1031  this->SetDirty();
1032  }
1033  return;
1034  }
1035 
1037 
1038  bool current_class_valid = this->livery_class == LC_OTHER || this->livery_class >= LC_GROUP_RAIL;
1039  if (_settings_client.gui.liveries == LIT_ALL || (_settings_client.gui.liveries == LIT_COMPANY && this->window_number == _local_company)) {
1040  for (LiveryScheme scheme = LS_DEFAULT; scheme < LS_END; scheme++) {
1042  if (_livery_class[scheme] == this->livery_class) current_class_valid = true;
1043  this->EnableWidget(WID_SCL_CLASS_GENERAL + _livery_class[scheme]);
1044  } else if (this->livery_class < LC_GROUP_RAIL) {
1045  ClrBit(this->sel, scheme);
1046  }
1047  }
1048  }
1049 
1050  if (!current_class_valid) {
1051  Point pt = {0, 0};
1052  this->OnClick(pt, WID_SCL_CLASS_GENERAL, 1);
1053  }
1054  }
1055 };
1056 
1057 static const NWidgetPart _nested_select_company_livery_widgets [] = {
1059  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1060  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCL_CAPTION), SetDataTip(STR_LIVERY_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1061  EndContainer(),
1063  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_GENERAL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_COMPANY_GENERAL, STR_LIVERY_GENERAL_TOOLTIP),
1064  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRAINLIST, STR_LIVERY_TRAIN_TOOLTIP),
1065  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_ROAD), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_TRUCKLIST, STR_LIVERY_ROAD_VEHICLE_TOOLTIP),
1066  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_SHIPLIST, STR_LIVERY_SHIP_TOOLTIP),
1067  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_CLASS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_IMG_AIRPLANESLIST, STR_LIVERY_AIRCRAFT_TOOLTIP),
1068  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_RAIL), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_TRAIN, STR_LIVERY_TRAIN_TOOLTIP),
1069  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),
1070  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_SHIP), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_SHIP, STR_LIVERY_SHIP_TOOLTIP),
1071  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCL_GROUPS_AIRCRAFT), SetMinimalSize(22, 22), SetFill(0, 1), SetDataTip(SPR_GROUP_LIVERY_AIRCRAFT, STR_LIVERY_AIRCRAFT_TOOLTIP),
1072  NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(90, 22), SetFill(1, 1), EndContainer(),
1073  EndContainer(),
1075  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCL_SPACER_DROPDOWN), SetMinimalSize(150, 12), SetFill(1, 1), EndContainer(),
1076  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_PRI_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1), SetDataTip(STR_BLACK_STRING, STR_LIVERY_PRIMARY_TOOLTIP),
1077  NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_SCL_SEC_COL_DROPDOWN), SetMinimalSize(125, 12), SetFill(0, 1),
1078  SetDataTip(STR_BLACK_STRING, STR_LIVERY_SECONDARY_TOOLTIP),
1079  EndContainer(),
1081  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),
1084  NWidget(WWT_RESIZEBOX, COLOUR_GREY),
1085  EndContainer(),
1086  EndContainer(),
1087 };
1088 
1089 static WindowDesc _select_company_livery_desc(
1090  WDP_AUTO, "company_livery", 0, 0,
1092  0,
1093  _nested_select_company_livery_widgets, lengthof(_nested_select_company_livery_widgets)
1094 );
1095 
1096 void ShowCompanyLiveryWindow(CompanyID company, GroupID group)
1097 {
1099  if (w == NULL) {
1100  new SelectCompanyLiveryWindow(&_select_company_livery_desc, company, group);
1101  } else if (group != INVALID_GROUP) {
1102  w->SetSelectedGroup(group);
1103  }
1104 }
1105 
1113 void DrawCompanyManagerFace(CompanyManagerFace cmf, int colour, int x, int y)
1114 {
1116 
1117  bool has_moustache = !HasBit(ge, GENDER_FEMALE) && GetCompanyManagerFaceBits(cmf, CMFV_HAS_MOUSTACHE, ge) != 0;
1118  bool has_tie_earring = !HasBit(ge, GENDER_FEMALE) || GetCompanyManagerFaceBits(cmf, CMFV_HAS_TIE_EARRING, ge) != 0;
1119  bool has_glasses = GetCompanyManagerFaceBits(cmf, CMFV_HAS_GLASSES, ge) != 0;
1120  PaletteID pal;
1121 
1122  /* Modify eye colour palette only if 2 or more valid values exist */
1123  if (_cmf_info[CMFV_EYE_COLOUR].valid_values[ge] < 2) {
1124  pal = PAL_NONE;
1125  } else {
1126  switch (GetCompanyManagerFaceBits(cmf, CMFV_EYE_COLOUR, ge)) {
1127  default: NOT_REACHED();
1128  case 0: pal = PALETTE_TO_BROWN; break;
1129  case 1: pal = PALETTE_TO_BLUE; break;
1130  case 2: pal = PALETTE_TO_GREEN; break;
1131  }
1132  }
1133 
1134  /* Draw the gradient (background) */
1135  DrawSprite(SPR_GRADIENT, GENERAL_SPRITE_COLOUR(colour), x, y);
1136 
1137  for (CompanyManagerFaceVariable cmfv = CMFV_CHEEKS; cmfv < CMFV_END; cmfv++) {
1138  switch (cmfv) {
1139  case CMFV_MOUSTACHE: if (!has_moustache) continue; break;
1140  case CMFV_LIPS:
1141  case CMFV_NOSE: if (has_moustache) continue; break;
1142  case CMFV_TIE_EARRING: if (!has_tie_earring) continue; break;
1143  case CMFV_GLASSES: if (!has_glasses) continue; break;
1144  default: break;
1145  }
1146  DrawSprite(GetCompanyManagerFaceSprite(cmf, cmfv, ge), (cmfv == CMFV_EYEBROWS) ? pal : PAL_NONE, x, y);
1147  }
1148 }
1149 
1153  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1154  NWidget(WWT_CAPTION, COLOUR_GREY, WID_SCMF_CAPTION), SetDataTip(STR_FACE_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1155  NWidget(WWT_IMGBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL), SetDataTip(SPR_LARGE_SMALL_WINDOW, STR_FACE_ADVANCED_TOOLTIP),
1156  EndContainer(),
1157  NWidget(WWT_PANEL, COLOUR_GREY, WID_SCMF_SELECT_FACE),
1159  NWidget(NWID_HORIZONTAL), SetPIP(2, 2, 2),
1162  NWidget(NWID_SPACER), SetFill(1, 0),
1163  NWidget(WWT_EMPTY, COLOUR_GREY, WID_SCMF_FACE), SetMinimalSize(92, 119),
1164  NWidget(NWID_SPACER), SetFill(1, 0),
1165  EndContainer(),
1167  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_RANDOM_NEW_FACE), SetFill(1, 0), SetDataTip(STR_FACE_NEW_FACE_BUTTON, STR_FACE_NEW_FACE_TOOLTIP),
1168  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_LOADSAVE), // Load/number/save buttons under the portrait in the advanced view.
1170  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1171  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LOAD), SetFill(1, 0), SetDataTip(STR_FACE_LOAD, STR_FACE_LOAD_TOOLTIP),
1172  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_FACECODE), SetFill(1, 0), SetDataTip(STR_FACE_FACECODE, STR_FACE_FACECODE_TOOLTIP),
1173  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_SAVE), SetFill(1, 0), SetDataTip(STR_FACE_SAVE, STR_FACE_SAVE_TOOLTIP),
1174  NWidget(NWID_SPACER), SetMinimalSize(0, 5), SetFill(0, 1),
1175  EndContainer(),
1176  EndContainer(),
1177  EndContainer(),
1179  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON), SetFill(1, 0), SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP),
1181  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_MALEFEMALE), // Simple male/female face setting.
1183  NWidget(NWID_SPACER), SetFill(0, 1),
1184  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1185  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1186  NWidget(NWID_SPACER), SetFill(0, 1),
1187  EndContainer(),
1188  EndContainer(),
1189  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_SCMF_SEL_PARTS), // Advanced face parts setting.
1193  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_MALE2), SetFill(1, 0), SetDataTip(STR_FACE_MALE_BUTTON, STR_FACE_MALE_TOOLTIP),
1194  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_FEMALE2), SetFill(1, 0), SetDataTip(STR_FACE_FEMALE_BUTTON, STR_FACE_FEMALE_TOOLTIP),
1195  EndContainer(),
1198  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_EUR), SetFill(1, 0), SetDataTip(STR_FACE_EUROPEAN, STR_FACE_SELECT_EUROPEAN),
1199  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SCMF_ETHNICITY_AFR), SetFill(1, 0), SetDataTip(STR_FACE_AFRICAN, STR_FACE_SELECT_AFRICAN),
1200  EndContainer(),
1204  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_MOUSTACHE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_MOUSTACHE_EARRING_TOOLTIP),
1205  EndContainer(),
1207  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAS_GLASSES_TEXT), SetFill(1, 0),
1208  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAS_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP),
1209  EndContainer(),
1210  NWidget(NWID_SPACER), SetMinimalSize(0, 2), SetFill(1, 0),
1212  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_HAIR_TEXT), SetFill(1, 0),
1213  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_L), SetDataTip(AWV_DECREASE, STR_FACE_HAIR_TOOLTIP),
1214  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_HAIR), SetDataTip(STR_EMPTY, STR_FACE_HAIR_TOOLTIP),
1215  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_HAIR_R), SetDataTip(AWV_INCREASE, STR_FACE_HAIR_TOOLTIP),
1216  EndContainer(),
1218  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYEBROWS_TEXT), SetFill(1, 0),
1219  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_L), SetDataTip(AWV_DECREASE, STR_FACE_EYEBROWS_TOOLTIP),
1220  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYEBROWS), SetDataTip(STR_EMPTY, STR_FACE_EYEBROWS_TOOLTIP),
1221  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYEBROWS_R), SetDataTip(AWV_INCREASE, STR_FACE_EYEBROWS_TOOLTIP),
1222  EndContainer(),
1224  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_EYECOLOUR_TEXT), SetFill(1, 0),
1225  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_L), SetDataTip(AWV_DECREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1226  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR), SetDataTip(STR_EMPTY, STR_FACE_EYECOLOUR_TOOLTIP),
1227  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_EYECOLOUR_R), SetDataTip(AWV_INCREASE, STR_FACE_EYECOLOUR_TOOLTIP),
1228  EndContainer(),
1230  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_GLASSES_TEXT), SetFill(1, 0),
1231  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_L), SetDataTip(AWV_DECREASE, STR_FACE_GLASSES_TOOLTIP_2),
1232  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_GLASSES), SetDataTip(STR_EMPTY, STR_FACE_GLASSES_TOOLTIP_2),
1233  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_GLASSES_R), SetDataTip(AWV_INCREASE, STR_FACE_GLASSES_TOOLTIP_2),
1234  EndContainer(),
1236  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_NOSE_TEXT), SetFill(1, 0),
1237  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_L), SetDataTip(AWV_DECREASE, STR_FACE_NOSE_TOOLTIP),
1238  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_NOSE), SetDataTip(STR_EMPTY, STR_FACE_NOSE_TOOLTIP),
1239  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_NOSE_R), SetDataTip(AWV_INCREASE, STR_FACE_NOSE_TOOLTIP),
1240  EndContainer(),
1242  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_LIPS_MOUSTACHE_TEXT), SetFill(1, 0),
1243  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_L), SetDataTip(AWV_DECREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1244  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE), SetDataTip(STR_EMPTY, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1245  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_LIPS_MOUSTACHE_R), SetDataTip(AWV_INCREASE, STR_FACE_LIPS_MOUSTACHE_TOOLTIP),
1246  EndContainer(),
1248  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_CHIN_TEXT), SetFill(1, 0),
1249  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_L), SetDataTip(AWV_DECREASE, STR_FACE_CHIN_TOOLTIP),
1250  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CHIN), SetDataTip(STR_EMPTY, STR_FACE_CHIN_TOOLTIP),
1251  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_CHIN_R), SetDataTip(AWV_INCREASE, STR_FACE_CHIN_TOOLTIP),
1252  EndContainer(),
1254  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_JACKET_TEXT), SetFill(1, 0),
1255  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_L), SetDataTip(AWV_DECREASE, STR_FACE_JACKET_TOOLTIP),
1256  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_JACKET), SetDataTip(STR_EMPTY, STR_FACE_JACKET_TOOLTIP),
1257  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_JACKET_R), SetDataTip(AWV_INCREASE, STR_FACE_JACKET_TOOLTIP),
1258  EndContainer(),
1260  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_COLLAR_TEXT), SetFill(1, 0),
1261  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_L), SetDataTip(AWV_DECREASE, STR_FACE_COLLAR_TOOLTIP),
1262  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_COLLAR), SetDataTip(STR_EMPTY, STR_FACE_COLLAR_TOOLTIP),
1263  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_COLLAR_R), SetDataTip(AWV_INCREASE, STR_FACE_COLLAR_TOOLTIP),
1264  EndContainer(),
1266  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_SCMF_TIE_EARRING_TEXT), SetFill(1, 0),
1267  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_L), SetDataTip(AWV_DECREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1268  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING), SetDataTip(STR_EMPTY, STR_FACE_TIE_EARRING_TOOLTIP),
1269  NWidget(WWT_PUSHARROWBTN, COLOUR_GREY, WID_SCMF_TIE_EARRING_R), SetDataTip(AWV_INCREASE, STR_FACE_TIE_EARRING_TOOLTIP),
1270  EndContainer(),
1271  NWidget(NWID_SPACER), SetFill(0, 1),
1272  EndContainer(),
1273  EndContainer(),
1274  EndContainer(),
1275  EndContainer(),
1277  EndContainer(),
1279  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_CANCEL), SetFill(1, 0), SetDataTip(STR_BUTTON_CANCEL, STR_FACE_CANCEL_TOOLTIP),
1280  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SCMF_ACCEPT), SetFill(1, 0), SetDataTip(STR_BUTTON_OK, STR_FACE_OK_TOOLTIP),
1281  EndContainer(),
1282 };
1283 
1286 {
1288  bool advanced;
1289 
1291  bool is_female;
1293 
1296 
1297  static const StringID PART_TEXTS_IS_FEMALE[];
1298  static const StringID PART_TEXTS[];
1299 
1307  void DrawFaceStringLabel(byte widget_index, uint8 val, bool is_bool_widget) const
1308  {
1309  StringID str;
1310  const NWidgetCore *nwi_widget = this->GetWidget<NWidgetCore>(widget_index);
1311  if (!nwi_widget->IsDisabled()) {
1312  if (is_bool_widget) {
1313  /* if it a bool button write yes or no */
1314  str = (val != 0) ? STR_FACE_YES : STR_FACE_NO;
1315  } else {
1316  /* else write the value + 1 */
1317  SetDParam(0, val + 1);
1318  str = STR_JUST_INT;
1319  }
1320 
1321  /* Draw the value/bool in white (0xC). If the button clicked adds 1px to x and y text coordinates (IsWindowWidgetLowered()). */
1322  DrawString(nwi_widget->pos_x + nwi_widget->IsLowered(), nwi_widget->pos_x + nwi_widget->current_x - 1 - nwi_widget->IsLowered(),
1323  nwi_widget->pos_y + 1 + nwi_widget->IsLowered(), str, TC_WHITE, SA_HOR_CENTER);
1324  }
1325  }
1326 
1327  void UpdateData()
1328  {
1329  this->ge = (GenderEthnicity)GB(this->face, _cmf_info[CMFV_GEN_ETHN].offset, _cmf_info[CMFV_GEN_ETHN].length); // get the gender and ethnicity
1330  this->is_female = HasBit(this->ge, GENDER_FEMALE); // get the gender: 0 == male and 1 == female
1331  this->is_moust_male = !is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge) != 0; // is a male face with moustache
1332  }
1333 
1334 public:
1335  SelectCompanyManagerFaceWindow(WindowDesc *desc, Window *parent) : Window(desc)
1336  {
1337  this->advanced = false;
1338  this->CreateNestedTree();
1339  this->SelectDisplayPlanes(this->advanced);
1340  this->FinishInitNested(parent->window_number);
1341  this->parent = parent;
1342  this->owner = (Owner)this->window_number;
1343  this->face = Company::Get((CompanyID)this->window_number)->face;
1344 
1345  this->UpdateData();
1346  }
1347 
1352  void SelectDisplayPlanes(bool advanced)
1353  {
1354  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_LOADSAVE)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1355  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_PARTS)->SetDisplayedPlane(advanced ? 0 : SZSP_NONE);
1356  this->GetWidget<NWidgetStacked>(WID_SCMF_SEL_MALEFEMALE)->SetDisplayedPlane(advanced ? SZSP_NONE : 0);
1357  this->GetWidget<NWidgetCore>(WID_SCMF_RANDOM_NEW_FACE)->widget_data = advanced ? STR_FACE_RANDOM : STR_FACE_NEW_FACE_BUTTON;
1358 
1359  NWidgetCore *wi = this->GetWidget<NWidgetCore>(WID_SCMF_TOGGLE_LARGE_SMALL_BUTTON);
1360  if (advanced) {
1361  wi->SetDataTip(STR_FACE_SIMPLE, STR_FACE_SIMPLE_TOOLTIP);
1362  } else {
1363  wi->SetDataTip(STR_FACE_ADVANCED, STR_FACE_ADVANCED_TOOLTIP);
1364  }
1365  }
1366 
1367  virtual void OnInit()
1368  {
1369  /* Size of the boolean yes/no button. */
1370  Dimension yesno_dim = maxdim(GetStringBoundingBox(STR_FACE_YES), GetStringBoundingBox(STR_FACE_NO));
1371  yesno_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1372  yesno_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1373  /* Size of the number button + arrows. */
1374  Dimension number_dim = {0, 0};
1375  for (int val = 1; val <= 12; val++) {
1376  SetDParam(0, val);
1377  number_dim = maxdim(number_dim, GetStringBoundingBox(STR_JUST_INT));
1378  }
1379  uint arrows_width = GetSpriteSize(SPR_ARROW_LEFT).width + GetSpriteSize(SPR_ARROW_RIGHT).width + 2 * (WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT);
1380  number_dim.width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT + arrows_width;
1381  number_dim.height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1382  /* Compute width of both buttons. */
1383  yesno_dim.width = max(yesno_dim.width, number_dim.width);
1384  number_dim.width = yesno_dim.width - arrows_width;
1385 
1386  this->yesno_dim = yesno_dim;
1387  this->number_dim = number_dim;
1388  }
1389 
1390  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1391  {
1392  switch (widget) {
1393  case WID_SCMF_FACE: {
1394  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
1395  size->width = max(size->width, face_size.width);
1396  size->height = max(size->height, face_size.height);
1397  break;
1398  }
1399 
1402  int offset = (widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2;
1403  *size = maxdim(GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset]), GetStringBoundingBox(PART_TEXTS_IS_FEMALE[offset + 1]));
1404  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1405  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1406  break;
1407  }
1408 
1410  *size = maxdim(GetStringBoundingBox(STR_FACE_LIPS), GetStringBoundingBox(STR_FACE_MOUSTACHE));
1411  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1412  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1413  break;
1414 
1416  case WID_SCMF_HAIR_TEXT:
1419  case WID_SCMF_GLASSES_TEXT:
1420  case WID_SCMF_NOSE_TEXT:
1421  case WID_SCMF_CHIN_TEXT:
1422  case WID_SCMF_JACKET_TEXT:
1423  case WID_SCMF_COLLAR_TEXT:
1424  *size = GetStringBoundingBox(PART_TEXTS[widget - WID_SCMF_HAS_GLASSES_TEXT]);
1425  size->width += WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
1426  size->height += WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM;
1427  break;
1428 
1430  case WID_SCMF_HAS_GLASSES:
1431  *size = this->yesno_dim;
1432  break;
1433 
1434  case WID_SCMF_EYECOLOUR:
1435  case WID_SCMF_CHIN:
1436  case WID_SCMF_EYEBROWS:
1438  case WID_SCMF_NOSE:
1439  case WID_SCMF_HAIR:
1440  case WID_SCMF_JACKET:
1441  case WID_SCMF_COLLAR:
1442  case WID_SCMF_TIE_EARRING:
1443  case WID_SCMF_GLASSES:
1444  *size = this->number_dim;
1445  break;
1446  }
1447  }
1448 
1449  virtual void OnPaint()
1450  {
1451  /* lower the non-selected gender button */
1452  this->SetWidgetsLoweredState(!this->is_female, WID_SCMF_MALE, WID_SCMF_MALE2, WIDGET_LIST_END);
1453  this->SetWidgetsLoweredState( this->is_female, WID_SCMF_FEMALE, WID_SCMF_FEMALE2, WIDGET_LIST_END);
1454 
1455  /* advanced company manager face selection window */
1456 
1457  /* lower the non-selected ethnicity button */
1458  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_EUR, !HasBit(this->ge, ETHNICITY_BLACK));
1459  this->SetWidgetLoweredState(WID_SCMF_ETHNICITY_AFR, HasBit(this->ge, ETHNICITY_BLACK));
1460 
1461 
1462  /* Disable dynamically the widgets which CompanyManagerFaceVariable has less than 2 options
1463  * (or in other words you haven't any choice).
1464  * If the widgets depend on a HAS-variable and this is false the widgets will be disabled, too. */
1465 
1466  /* Eye colour buttons */
1467  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYE_COLOUR].valid_values[this->ge] < 2,
1469 
1470  /* Chin buttons */
1471  this->SetWidgetsDisabledState(_cmf_info[CMFV_CHIN].valid_values[this->ge] < 2,
1473 
1474  /* Eyebrows buttons */
1475  this->SetWidgetsDisabledState(_cmf_info[CMFV_EYEBROWS].valid_values[this->ge] < 2,
1477 
1478  /* Lips or (if it a male face with a moustache) moustache buttons */
1479  this->SetWidgetsDisabledState(_cmf_info[this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS].valid_values[this->ge] < 2,
1481 
1482  /* Nose buttons | male faces with moustache haven't any nose options */
1483  this->SetWidgetsDisabledState(_cmf_info[CMFV_NOSE].valid_values[this->ge] < 2 || this->is_moust_male,
1485 
1486  /* Hair buttons */
1487  this->SetWidgetsDisabledState(_cmf_info[CMFV_HAIR].valid_values[this->ge] < 2,
1489 
1490  /* Jacket buttons */
1491  this->SetWidgetsDisabledState(_cmf_info[CMFV_JACKET].valid_values[this->ge] < 2,
1493 
1494  /* Collar buttons */
1495  this->SetWidgetsDisabledState(_cmf_info[CMFV_COLLAR].valid_values[this->ge] < 2,
1497 
1498  /* Tie/earring buttons | female faces without earring haven't any earring options */
1499  this->SetWidgetsDisabledState(_cmf_info[CMFV_TIE_EARRING].valid_values[this->ge] < 2 ||
1500  (this->is_female && GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge) == 0),
1502 
1503  /* Glasses buttons | faces without glasses haven't any glasses options */
1504  this->SetWidgetsDisabledState(_cmf_info[CMFV_GLASSES].valid_values[this->ge] < 2 || GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge) == 0,
1506 
1507  this->DrawWidgets();
1508  }
1509 
1510  virtual void DrawWidget(const Rect &r, int widget) const
1511  {
1512  switch (widget) {
1515  StringID str = PART_TEXTS_IS_FEMALE[(widget - WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT) * 2 + this->is_female];
1516  DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, str, TC_GOLD, SA_RIGHT);
1517  break;
1518  }
1519 
1521  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);
1522  break;
1523 
1525  case WID_SCMF_HAIR_TEXT:
1528  case WID_SCMF_GLASSES_TEXT:
1529  case WID_SCMF_NOSE_TEXT:
1530  case WID_SCMF_CHIN_TEXT:
1531  case WID_SCMF_JACKET_TEXT:
1532  case WID_SCMF_COLLAR_TEXT:
1533  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);
1534  break;
1535 
1536 
1538  if (this->is_female) { // Only for female faces
1539  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_TIE_EARRING, this->ge), true);
1540  } else { // Only for male faces
1541  this->DrawFaceStringLabel(WID_SCMF_HAS_MOUSTACHE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_HAS_MOUSTACHE, this->ge), true);
1542  }
1543  break;
1544 
1545  case WID_SCMF_TIE_EARRING:
1546  this->DrawFaceStringLabel(WID_SCMF_TIE_EARRING, GetCompanyManagerFaceBits(this->face, CMFV_TIE_EARRING, this->ge), false);
1547  break;
1548 
1550  if (this->is_moust_male) { // Only for male faces with moustache
1551  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_MOUSTACHE, this->ge), false);
1552  } else { // Only for female faces or male faces without moustache
1553  this->DrawFaceStringLabel(WID_SCMF_LIPS_MOUSTACHE, GetCompanyManagerFaceBits(this->face, CMFV_LIPS, this->ge), false);
1554  }
1555  break;
1556 
1557  case WID_SCMF_HAS_GLASSES:
1558  this->DrawFaceStringLabel(WID_SCMF_HAS_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_HAS_GLASSES, this->ge), true );
1559  break;
1560 
1561  case WID_SCMF_HAIR:
1562  this->DrawFaceStringLabel(WID_SCMF_HAIR, GetCompanyManagerFaceBits(this->face, CMFV_HAIR, this->ge), false);
1563  break;
1564 
1565  case WID_SCMF_EYEBROWS:
1566  this->DrawFaceStringLabel(WID_SCMF_EYEBROWS, GetCompanyManagerFaceBits(this->face, CMFV_EYEBROWS, this->ge), false);
1567  break;
1568 
1569  case WID_SCMF_EYECOLOUR:
1570  this->DrawFaceStringLabel(WID_SCMF_EYECOLOUR, GetCompanyManagerFaceBits(this->face, CMFV_EYE_COLOUR, this->ge), false);
1571  break;
1572 
1573  case WID_SCMF_GLASSES:
1574  this->DrawFaceStringLabel(WID_SCMF_GLASSES, GetCompanyManagerFaceBits(this->face, CMFV_GLASSES, this->ge), false);
1575  break;
1576 
1577  case WID_SCMF_NOSE:
1578  this->DrawFaceStringLabel(WID_SCMF_NOSE, GetCompanyManagerFaceBits(this->face, CMFV_NOSE, this->ge), false);
1579  break;
1580 
1581  case WID_SCMF_CHIN:
1582  this->DrawFaceStringLabel(WID_SCMF_CHIN, GetCompanyManagerFaceBits(this->face, CMFV_CHIN, this->ge), false);
1583  break;
1584 
1585  case WID_SCMF_JACKET:
1586  this->DrawFaceStringLabel(WID_SCMF_JACKET, GetCompanyManagerFaceBits(this->face, CMFV_JACKET, this->ge), false);
1587  break;
1588 
1589  case WID_SCMF_COLLAR:
1590  this->DrawFaceStringLabel(WID_SCMF_COLLAR, GetCompanyManagerFaceBits(this->face, CMFV_COLLAR, this->ge), false);
1591  break;
1592 
1593  case WID_SCMF_FACE:
1594  DrawCompanyManagerFace(this->face, Company::Get((CompanyID)this->window_number)->colour, r.left, r.top);
1595  break;
1596  }
1597  }
1598 
1599  virtual void OnClick(Point pt, int widget, int click_count)
1600  {
1601  switch (widget) {
1602  /* Toggle size, advanced/simple face selection */
1605  this->advanced = !this->advanced;
1606  this->SelectDisplayPlanes(this->advanced);
1607  this->ReInit();
1608  break;
1609 
1610  /* OK button */
1611  case WID_SCMF_ACCEPT:
1612  DoCommandP(0, 0, this->face, CMD_SET_COMPANY_MANAGER_FACE);
1613  FALLTHROUGH;
1614 
1615  /* Cancel button */
1616  case WID_SCMF_CANCEL:
1617  delete this;
1618  break;
1619 
1620  /* Load button */
1621  case WID_SCMF_LOAD:
1622  this->face = _company_manager_face;
1623  ScaleAllCompanyManagerFaceBits(this->face);
1624  ShowErrorMessage(STR_FACE_LOAD_DONE, INVALID_STRING_ID, WL_INFO);
1625  this->UpdateData();
1626  this->SetDirty();
1627  break;
1628 
1629  /* 'Company manager face number' button, view and/or set company manager face number */
1630  case WID_SCMF_FACECODE:
1631  SetDParam(0, this->face);
1632  ShowQueryString(STR_JUST_INT, STR_FACE_FACECODE_CAPTION, 10 + 1, this, CS_NUMERAL, QSF_NONE);
1633  break;
1634 
1635  /* Save button */
1636  case WID_SCMF_SAVE:
1637  _company_manager_face = this->face;
1638  ShowErrorMessage(STR_FACE_SAVE_DONE, INVALID_STRING_ID, WL_INFO);
1639  break;
1640 
1641  /* Toggle gender (male/female) button */
1642  case WID_SCMF_MALE:
1643  case WID_SCMF_FEMALE:
1644  case WID_SCMF_MALE2:
1645  case WID_SCMF_FEMALE2:
1646  SetCompanyManagerFaceBits(this->face, CMFV_GENDER, this->ge, (widget == WID_SCMF_FEMALE || widget == WID_SCMF_FEMALE2));
1647  ScaleAllCompanyManagerFaceBits(this->face);
1648  this->UpdateData();
1649  this->SetDirty();
1650  break;
1651 
1652  /* Randomize face button */
1654  RandomCompanyManagerFaceBits(this->face, this->ge, this->advanced);
1655  this->UpdateData();
1656  this->SetDirty();
1657  break;
1658 
1659  /* Toggle ethnicity (european/african) button */
1662  SetCompanyManagerFaceBits(this->face, CMFV_ETHNICITY, this->ge, widget - WID_SCMF_ETHNICITY_EUR);
1663  ScaleAllCompanyManagerFaceBits(this->face);
1664  this->UpdateData();
1665  this->SetDirty();
1666  break;
1667 
1668  default:
1669  /* Here all buttons from WID_SCMF_HAS_MOUSTACHE_EARRING to WID_SCMF_GLASSES_R are handled.
1670  * First it checks which CompanyManagerFaceVariable is being changed, and then either
1671  * a: invert the value for boolean variables, or
1672  * b: it checks inside of IncreaseCompanyManagerFaceBits() if a left (_L) butten is pressed and then decrease else increase the variable */
1673  if (widget >= WID_SCMF_HAS_MOUSTACHE_EARRING && widget <= WID_SCMF_GLASSES_R) {
1674  CompanyManagerFaceVariable cmfv; // which CompanyManagerFaceVariable shall be edited
1675 
1676  if (widget < WID_SCMF_EYECOLOUR_L) { // Bool buttons
1677  switch (widget - WID_SCMF_HAS_MOUSTACHE_EARRING) {
1678  default: NOT_REACHED();
1679  case 0: cmfv = this->is_female ? CMFV_HAS_TIE_EARRING : CMFV_HAS_MOUSTACHE; break; // Has earring/moustache button
1680  case 1: cmfv = CMFV_HAS_GLASSES; break; // Has glasses button
1681  }
1682  SetCompanyManagerFaceBits(this->face, cmfv, this->ge, !GetCompanyManagerFaceBits(this->face, cmfv, this->ge));
1683  ScaleAllCompanyManagerFaceBits(this->face);
1684  } else { // Value buttons
1685  switch ((widget - WID_SCMF_EYECOLOUR_L) / 3) {
1686  default: NOT_REACHED();
1687  case 0: cmfv = CMFV_EYE_COLOUR; break; // Eye colour buttons
1688  case 1: cmfv = CMFV_CHIN; break; // Chin buttons
1689  case 2: cmfv = CMFV_EYEBROWS; break; // Eyebrows buttons
1690  case 3: cmfv = this->is_moust_male ? CMFV_MOUSTACHE : CMFV_LIPS; break; // Moustache or lips buttons
1691  case 4: cmfv = CMFV_NOSE; break; // Nose buttons
1692  case 5: cmfv = CMFV_HAIR; break; // Hair buttons
1693  case 6: cmfv = CMFV_JACKET; break; // Jacket buttons
1694  case 7: cmfv = CMFV_COLLAR; break; // Collar buttons
1695  case 8: cmfv = CMFV_TIE_EARRING; break; // Tie/earring buttons
1696  case 9: cmfv = CMFV_GLASSES; break; // Glasses buttons
1697  }
1698  /* 0 == left (_L), 1 == middle or 2 == right (_R) - button click */
1699  IncreaseCompanyManagerFaceBits(this->face, cmfv, this->ge, (((widget - WID_SCMF_EYECOLOUR_L) % 3) != 0) ? 1 : -1);
1700  }
1701  this->UpdateData();
1702  this->SetDirty();
1703  }
1704  break;
1705  }
1706  }
1707 
1708  virtual void OnQueryTextFinished(char *str)
1709  {
1710  if (str == NULL) return;
1711  /* Set a new company manager face number */
1712  if (!StrEmpty(str)) {
1713  this->face = strtoul(str, NULL, 10);
1714  ScaleAllCompanyManagerFaceBits(this->face);
1715  ShowErrorMessage(STR_FACE_FACECODE_SET, INVALID_STRING_ID, WL_INFO);
1716  this->UpdateData();
1717  this->SetDirty();
1718  } else {
1719  ShowErrorMessage(STR_FACE_FACECODE_ERR, INVALID_STRING_ID, WL_INFO);
1720  }
1721  }
1722 };
1723 
1726  STR_FACE_MOUSTACHE, STR_FACE_EARRING, // WID_SCMF_HAS_MOUSTACHE_EARRING_TEXT
1727  STR_FACE_TIE, STR_FACE_EARRING, // WID_SCMF_TIE_EARRING_TEXT
1728 };
1729 
1732  STR_FACE_GLASSES, // WID_SCMF_HAS_GLASSES_TEXT
1733  STR_FACE_HAIR, // WID_SCMF_HAIR_TEXT
1734  STR_FACE_EYEBROWS, // WID_SCMF_EYEBROWS_TEXT
1735  STR_FACE_EYECOLOUR, // WID_SCMF_EYECOLOUR_TEXT
1736  STR_FACE_GLASSES, // WID_SCMF_GLASSES_TEXT
1737  STR_FACE_NOSE, // WID_SCMF_NOSE_TEXT
1738  STR_FACE_CHIN, // WID_SCMF_CHIN_TEXT
1739  STR_FACE_JACKET, // WID_SCMF_JACKET_TEXT
1740  STR_FACE_COLLAR, // WID_SCMF_COLLAR_TEXT
1741 };
1742 
1745  WDP_AUTO, "company_face", 0, 0,
1748  _nested_select_company_manager_face_widgets, lengthof(_nested_select_company_manager_face_widgets)
1749 );
1750 
1757 {
1758  if (!Company::IsValidID((CompanyID)parent->window_number)) return;
1759 
1761  new SelectCompanyManagerFaceWindow(&_select_company_manager_face_desc, parent);
1762 }
1763 
1764 static const NWidgetPart _nested_company_infrastructure_widgets[] = {
1766  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
1767  NWidget(WWT_CAPTION, COLOUR_GREY, WID_CI_CAPTION), SetDataTip(STR_COMPANY_INFRASTRUCTURE_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
1768  NWidget(WWT_SHADEBOX, COLOUR_GREY),
1769  NWidget(WWT_STICKYBOX, COLOUR_GREY),
1770  EndContainer(),
1771  NWidget(WWT_PANEL, COLOUR_GREY),
1773  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1774  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1775  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_RAIL_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1776  EndContainer(),
1777  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1778  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1779  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_ROAD_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1780  EndContainer(),
1781  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1782  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_DESC), SetMinimalTextLines(2, 0), SetFill(1, 0),
1783  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_WATER_COUNT), SetMinimalTextLines(2, 0), SetFill(0, 1),
1784  EndContainer(),
1785  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1786  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_DESC), SetMinimalTextLines(3, 0), SetFill(1, 0),
1787  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_STATION_COUNT), SetMinimalTextLines(3, 0), SetFill(0, 1),
1788  EndContainer(),
1789  NWidget(NWID_HORIZONTAL), SetPIP(2, 4, 2),
1790  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL_DESC), SetFill(1, 0),
1791  NWidget(WWT_EMPTY, COLOUR_GREY, WID_CI_TOTAL), SetFill(0, 1),
1792  EndContainer(),
1793  EndContainer(),
1794  EndContainer(),
1795 };
1796 
1801 {
1804 
1806 
1807  CompanyInfrastructureWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
1808  {
1809  this->UpdateRailRoadTypes();
1810 
1811  this->InitNested(window_number);
1812  this->owner = (Owner)this->window_number;
1813  }
1814 
1815  void UpdateRailRoadTypes()
1816  {
1817  this->railtypes = RAILTYPES_NONE;
1818  this->roadtypes = ROADTYPES_ROAD; // Road is always available.
1819 
1820  /* Find the used railtypes. */
1821  Engine *e;
1822  FOR_ALL_ENGINES_OF_TYPE(e, VEH_TRAIN) {
1823  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1824 
1825  this->railtypes |= GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes;
1826  }
1827 
1828  /* Get the date introduced railtypes as well. */
1829  this->railtypes = AddDateIntroducedRailTypes(this->railtypes, MAX_DAY);
1830 
1831  /* Tram is only visible when there will be a tram. */
1832  FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) {
1833  if (!HasBit(e->info.climates, _settings_game.game_creation.landscape)) continue;
1834  if (!HasBit(e->info.misc_flags, EF_ROAD_TRAM)) continue;
1835 
1836  this->roadtypes |= ROADTYPES_TRAM;
1837  break;
1838  }
1839  }
1840 
1843  {
1844  const Company *c = Company::Get((CompanyID)this->window_number);
1845  Money total;
1846 
1847  uint32 rail_total = c->infrastructure.GetRailTotal();
1848  for (RailType rt = RAILTYPE_BEGIN; rt != RAILTYPE_END; rt++) {
1849  if (HasBit(this->railtypes, rt)) total += RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total);
1850  }
1852 
1855 
1858  total += AirportMaintenanceCost(c->index);
1859 
1860  return total;
1861  }
1862 
1863  virtual void SetStringParameters(int widget) const
1864  {
1865  switch (widget) {
1866  case WID_CI_CAPTION:
1867  SetDParam(0, (CompanyID)this->window_number);
1868  break;
1869  }
1870  }
1871 
1872  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
1873  {
1874  const Company *c = Company::Get((CompanyID)this->window_number);
1875 
1876  switch (widget) {
1877  case WID_CI_RAIL_DESC: {
1878  uint lines = 1;
1879 
1880  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT).width);
1881 
1882  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1883  if (HasBit(this->railtypes, rt)) {
1884  lines++;
1885  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
1886  size->width = max(size->width, GetStringBoundingBox(STR_WHITE_STRING).width + WD_FRAMERECT_LEFT);
1887  }
1888  }
1889  if (this->railtypes != RAILTYPES_NONE) {
1890  lines++;
1891  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS).width + WD_FRAMERECT_LEFT);
1892  }
1893 
1894  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1895  break;
1896  }
1897 
1898  case WID_CI_ROAD_DESC: {
1899  uint lines = 1;
1900 
1901  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT).width);
1902 
1903  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
1904  lines++;
1905  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD).width + WD_FRAMERECT_LEFT);
1906  }
1907  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
1908  lines++;
1909  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY).width + WD_FRAMERECT_LEFT);
1910  }
1911 
1912  size->height = max(size->height, lines * FONT_HEIGHT_NORMAL);
1913  break;
1914  }
1915 
1916  case WID_CI_WATER_DESC:
1917  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT).width);
1918  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS).width + WD_FRAMERECT_LEFT);
1919  break;
1920 
1921  case WID_CI_STATION_DESC:
1922  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT).width);
1923  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS).width + WD_FRAMERECT_LEFT);
1924  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS).width + WD_FRAMERECT_LEFT);
1925  break;
1926 
1927  case WID_CI_RAIL_COUNT:
1928  case WID_CI_ROAD_COUNT:
1929  case WID_CI_WATER_COUNT:
1930  case WID_CI_STATION_COUNT:
1931  case WID_CI_TOTAL: {
1932  /* Find the maximum count that is displayed. */
1933  uint32 max_val = 1000; // Some random number to reserve enough space.
1934  Money max_cost = 10000; // Some random number to reserve enough space.
1935  uint32 rail_total = c->infrastructure.GetRailTotal();
1936  for (RailType rt = RAILTYPE_BEGIN; rt < RAILTYPE_END; rt++) {
1937  max_val = max(max_val, c->infrastructure.rail[rt]);
1938  max_cost = max(max_cost, RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
1939  }
1940  max_val = max(max_val, c->infrastructure.signal);
1941  max_cost = max(max_cost, SignalMaintenanceCost(c->infrastructure.signal));
1942  for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) {
1943  max_val = max(max_val, c->infrastructure.road[rt]);
1944  max_cost = max(max_cost, RoadMaintenanceCost(rt, c->infrastructure.road[rt]));
1945  }
1946  max_val = max(max_val, c->infrastructure.water);
1947  max_cost = max(max_cost, CanalMaintenanceCost(c->infrastructure.water));
1948  max_val = max(max_val, c->infrastructure.station);
1949  max_cost = max(max_cost, StationMaintenanceCost(c->infrastructure.station));
1950  max_val = max(max_val, c->infrastructure.airport);
1951  max_cost = max(max_cost, AirportMaintenanceCost(c->index));
1952 
1953  SetDParamMaxValue(0, max_val);
1954  uint count_width = GetStringBoundingBox(STR_WHITE_COMMA).width + 20; // Reserve some wiggle room
1955 
1957  SetDParamMaxValue(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
1958  this->total_width = GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width + 20;
1959  size->width = max(size->width, this->total_width);
1960 
1961  SetDParamMaxValue(0, max_cost * 12); // Convert to per year
1962  count_width += max(this->total_width, GetStringBoundingBox(STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL).width);
1963  }
1964 
1965  size->width = max(size->width, count_width);
1966 
1967  /* Set height of the total line. */
1968  if (widget == WID_CI_TOTAL) {
1970  }
1971  break;
1972  }
1973  }
1974  }
1975 
1983  void DrawCountLine(const Rect &r, int &y, int count, Money monthly_cost) const
1984  {
1985  SetDParam(0, count);
1986  DrawString(r.left, r.right, y += FONT_HEIGHT_NORMAL, STR_WHITE_COMMA, TC_FROMSTRING, SA_RIGHT);
1987 
1989  SetDParam(0, monthly_cost * 12); // Convert to per year
1990  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
1991  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
1992  }
1993  }
1994 
1995  virtual void DrawWidget(const Rect &r, int widget) const
1996  {
1997  const Company *c = Company::Get((CompanyID)this->window_number);
1998  int y = r.top;
1999 
2000  int offs_left = _current_text_dir == TD_LTR ? WD_FRAMERECT_LEFT : 0;
2001  int offs_right = _current_text_dir == TD_LTR ? 0 : WD_FRAMERECT_LEFT;
2002 
2003  switch (widget) {
2004  case WID_CI_RAIL_DESC:
2005  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_RAIL_SECT);
2006 
2007  if (this->railtypes != RAILTYPES_NONE) {
2008  /* Draw name of each valid railtype. */
2009  RailType rt;
2011  if (HasBit(this->railtypes, rt)) {
2012  SetDParam(0, GetRailTypeInfo(rt)->strings.name);
2013  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_WHITE_STRING);
2014  }
2015  }
2016  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_SIGNALS);
2017  } else {
2018  /* No valid railtype. */
2019  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2020  }
2021 
2022  break;
2023 
2024  case WID_CI_RAIL_COUNT: {
2025  /* Draw infrastructure count for each valid railtype. */
2026  uint32 rail_total = c->infrastructure.GetRailTotal();
2027  RailType rt;
2029  if (HasBit(this->railtypes, rt)) {
2030  this->DrawCountLine(r, y, c->infrastructure.rail[rt], RailMaintenanceCost(rt, c->infrastructure.rail[rt], rail_total));
2031  }
2032  }
2033  if (this->railtypes != RAILTYPES_NONE) {
2034  this->DrawCountLine(r, y, c->infrastructure.signal, SignalMaintenanceCost(c->infrastructure.signal));
2035  }
2036  break;
2037  }
2038 
2039  case WID_CI_ROAD_DESC:
2040  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD_SECT);
2041 
2042  if (this->roadtypes != ROADTYPES_NONE) {
2043  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_ROAD);
2044  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_TRAMWAY);
2045  } else {
2046  /* No valid roadtypes. */
2047  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2048  }
2049 
2050  break;
2051 
2052  case WID_CI_ROAD_COUNT:
2053  if (HasBit(this->roadtypes, ROADTYPE_ROAD)) {
2055  }
2056  if (HasBit(this->roadtypes, ROADTYPE_TRAM)) {
2058  }
2059  break;
2060 
2061  case WID_CI_WATER_DESC:
2062  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_WATER_SECT);
2063  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_CANALS);
2064  break;
2065 
2066  case WID_CI_WATER_COUNT:
2067  this->DrawCountLine(r, y, c->infrastructure.water, CanalMaintenanceCost(c->infrastructure.water));
2068  break;
2069 
2070  case WID_CI_TOTAL:
2072  int left = _current_text_dir == TD_RTL ? r.right - this->total_width : r.left;
2073  GfxFillRect(left, y, left + this->total_width, y, PC_WHITE);
2074  y += EXP_LINESPACE;
2075  SetDParam(0, this->GetTotalMaintenanceCost() * 12); // Convert to per year
2076  DrawString(left, left + this->total_width, y, STR_COMPANY_INFRASTRUCTURE_VIEW_TOTAL, TC_FROMSTRING, SA_RIGHT);
2077  }
2078  break;
2079 
2080  case WID_CI_STATION_DESC:
2081  DrawString(r.left, r.right, y, STR_COMPANY_INFRASTRUCTURE_VIEW_STATION_SECT);
2082  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_STATIONS);
2083  DrawString(r.left + offs_left, r.right - offs_right, y += FONT_HEIGHT_NORMAL, STR_COMPANY_INFRASTRUCTURE_VIEW_AIRPORTS);
2084  break;
2085 
2086  case WID_CI_STATION_COUNT:
2087  this->DrawCountLine(r, y, c->infrastructure.station, StationMaintenanceCost(c->infrastructure.station));
2088  this->DrawCountLine(r, y, c->infrastructure.airport, AirportMaintenanceCost(c->index));
2089  break;
2090  }
2091  }
2092 
2098  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2099  {
2100  if (!gui_scope) return;
2101 
2102  this->UpdateRailRoadTypes();
2103  this->ReInit();
2104  }
2105 };
2106 
2107 static WindowDesc _company_infrastructure_desc(
2108  WDP_AUTO, "company_infrastructure", 0, 0,
2110  0,
2111  _nested_company_infrastructure_widgets, lengthof(_nested_company_infrastructure_widgets)
2112 );
2113 
2119 {
2120  if (!Company::IsValidID(company)) return;
2121  AllocateWindowDescFront<CompanyInfrastructureWindow>(&_company_infrastructure_desc, company);
2122 }
2123 
2124 static const NWidgetPart _nested_company_widgets[] = {
2126  NWidget(WWT_CLOSEBOX, COLOUR_GREY),
2127  NWidget(WWT_CAPTION, COLOUR_GREY, WID_C_CAPTION), SetDataTip(STR_COMPANY_VIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2128  NWidget(WWT_SHADEBOX, COLOUR_GREY),
2129  NWidget(WWT_STICKYBOX, COLOUR_GREY),
2130  EndContainer(),
2131  NWidget(WWT_PANEL, COLOUR_GREY),
2132  NWidget(NWID_HORIZONTAL), SetPIP(4, 6, 4),
2133  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2134  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE), SetMinimalSize(92, 119), SetFill(1, 0),
2135  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_FACE_TITLE), SetFill(1, 1), SetMinimalTextLines(2, 0),
2136  EndContainer(),
2139  NWidget(NWID_VERTICAL), SetPIP(4, 5, 5),
2140  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INAUGURATION), SetDataTip(STR_COMPANY_VIEW_INAUGURATED_TITLE, STR_NULL), SetFill(1, 0),
2141  NWidget(NWID_HORIZONTAL), SetPIP(0, 5, 0),
2142  NWidget(WWT_LABEL, COLOUR_GREY, WID_C_DESC_COLOUR_SCHEME), SetDataTip(STR_COMPANY_VIEW_COLOUR_SCHEME_TITLE, STR_NULL),
2143  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_COLOUR_SCHEME_EXAMPLE), SetMinimalSize(30, 0), SetFill(0, 1),
2144  NWidget(NWID_SPACER), SetFill(1, 0),
2145  EndContainer(),
2146  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2148  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_VEHICLE), SetDataTip(STR_COMPANY_VIEW_VEHICLES_TITLE, STR_NULL),
2149  NWidget(NWID_SPACER), SetFill(0, 1),
2150  EndContainer(),
2152  NWidget(NWID_SPACER), SetFill(1, 0),
2153  EndContainer(),
2154  EndContainer(),
2155  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2157  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),
2158  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),
2159  EndContainer(),
2160  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_RELOCATE),
2161  NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_C_RELOCATE_HQ), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_RELOCATE_HQ, STR_COMPANY_VIEW_RELOCATE_COMPANY_HEADQUARTERS),
2163  EndContainer(),
2164  NWidget(NWID_SPACER), SetFill(0, 1),
2165  EndContainer(),
2166  EndContainer(),
2167  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_COMPANY_VALUE), SetDataTip(STR_COMPANY_VIEW_COMPANY_VALUE, STR_NULL), SetFill(1, 0),
2168  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2169  NWidget(NWID_HORIZONTAL), SetPIP(0, 4, 0),
2171  NWidget(WWT_TEXT, COLOUR_GREY, WID_C_DESC_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE, STR_NULL),
2172  NWidget(NWID_SPACER), SetFill(0, 1),
2173  EndContainer(),
2176  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_VIEW_INFRASTRUCTURE), SetDataTip(STR_COMPANY_VIEW_INFRASTRUCTURE_BUTTON, STR_COMPANY_VIEW_INFRASTRUCTURE_TOOLTIP),
2177  NWidget(NWID_SPACER), SetFill(0, 1), SetMinimalSize(90, 0),
2178  EndContainer(),
2179  EndContainer(),
2180  EndContainer(),
2183  NWidget(NWID_VERTICAL), SetPIP(5, 5, 4),
2184  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_C_DESC_OWNERS), SetMinimalTextLines(3, 0),
2185  NWidget(NWID_SPACER), SetFill(0, 1),
2186  EndContainer(),
2187  EndContainer(),
2188  NWidget(NWID_VERTICAL), SetPIP(4, 2, 4),
2189  NWidget(NWID_SPACER), SetMinimalSize(90, 0), SetFill(0, 1),
2190  /* Multi player buttons. */
2192  NWidget(WWT_EMPTY, COLOUR_GREY, WID_C_HAS_PASSWORD),
2194  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_PASSWORD), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_PASSWORD, STR_COMPANY_VIEW_PASSWORD_TOOLTIP),
2195  NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_C_COMPANY_JOIN), SetFill(1, 0), SetDataTip(STR_COMPANY_VIEW_JOIN, STR_COMPANY_VIEW_JOIN_TOOLTIP),
2196  EndContainer(),
2197  EndContainer(),
2198  EndContainer(),
2199  EndContainer(),
2200  EndContainer(),
2201  EndContainer(),
2202  EndContainer(),
2203  /* Button bars at the bottom. */
2204  NWidget(NWID_SELECTION, INVALID_COLOUR, WID_C_SELECT_BUTTONS),
2206  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),
2207  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),
2208  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),
2209  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),
2210  EndContainer(),
2212  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),
2213  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),
2214  EndContainer(),
2215  EndContainer(),
2216 };
2217 
2218 int GetAmountOwnedBy(const Company *c, Owner owner)
2219 {
2220  return (c->share_owners[0] == owner) +
2221  (c->share_owners[1] == owner) +
2222  (c->share_owners[2] == owner) +
2223  (c->share_owners[3] == owner);
2224 }
2225 
2228  STR_COMPANY_VIEW_TRAINS, STR_COMPANY_VIEW_ROAD_VEHICLES, STR_COMPANY_VIEW_SHIPS, STR_COMPANY_VIEW_AIRCRAFT
2229 };
2230 
2235 {
2236  CompanyWidgets query_widget;
2237 
2240  /* Display planes of the #WID_C_SELECT_MULTIPLAYER selection widget. */
2241  CWP_MP_C_PWD = 0,
2243 
2244  /* Display planes of the #WID_C_SELECT_VIEW_BUILD_HQ selection widget. */
2245  CWP_VB_VIEW = 0,
2247 
2248  /* Display planes of the #WID_C_SELECT_RELOCATE selection widget. */
2249  CWP_RELOCATE_SHOW = 0,
2251 
2252  /* Display planes of the #WID_C_SELECT_BUTTONS selection widget. */
2253  CWP_BUTTONS_LOCAL = 0,
2255  };
2256 
2257  CompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2258  {
2259  this->InitNested(window_number);
2260  this->owner = (Owner)this->window_number;
2261  this->OnInvalidateData();
2262  }
2263 
2264  virtual void OnPaint()
2265  {
2266  const Company *c = Company::Get((CompanyID)this->window_number);
2267  bool local = this->window_number == _local_company;
2268 
2269  if (!this->IsShaded()) {
2270  bool reinit = false;
2271 
2272  /* Button bar selection. */
2273  int plane = local ? CWP_BUTTONS_LOCAL : CWP_BUTTONS_OTHER;
2274  NWidgetStacked *wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_BUTTONS);
2275  if (plane != wi->shown_plane) {
2276  wi->SetDisplayedPlane(plane);
2277  this->InvalidateData();
2278  return;
2279  }
2280 
2281  /* Build HQ button handling. */
2282  plane = (local && c->location_of_HQ == INVALID_TILE) ? CWP_VB_BUILD : CWP_VB_VIEW;
2283  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_VIEW_BUILD_HQ);
2284  if (plane != wi->shown_plane) {
2285  wi->SetDisplayedPlane(plane);
2286  this->SetDirty();
2287  return;
2288  }
2289 
2290  this->SetWidgetDisabledState(WID_C_VIEW_HQ, c->location_of_HQ == INVALID_TILE);
2291 
2292  /* Enable/disable 'Relocate HQ' button. */
2293  plane = (!local || c->location_of_HQ == INVALID_TILE) ? CWP_RELOCATE_HIDE : CWP_RELOCATE_SHOW;
2294  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_RELOCATE);
2295  if (plane != wi->shown_plane) {
2296  wi->SetDisplayedPlane(plane);
2297  this->SetDirty();
2298  return;
2299  }
2300 
2301  /* Owners of company */
2302  plane = SZSP_HORIZONTAL;
2303  for (uint i = 0; i < lengthof(c->share_owners); i++) {
2304  if (c->share_owners[i] != INVALID_COMPANY) {
2305  plane = 0;
2306  break;
2307  }
2308  }
2309  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_DESC_OWNERS);
2310  if (plane != wi->shown_plane) {
2311  wi->SetDisplayedPlane(plane);
2312  reinit = true;
2313  }
2314 
2315  /* Multiplayer buttons. */
2316  plane = ((!_networking) ? (int)SZSP_NONE : (int)(local ? CWP_MP_C_PWD : CWP_MP_C_JOIN));
2317  wi = this->GetWidget<NWidgetStacked>(WID_C_SELECT_MULTIPLAYER);
2318  if (plane != wi->shown_plane) {
2319  wi->SetDisplayedPlane(plane);
2320  reinit = true;
2321  }
2322  this->SetWidgetDisabledState(WID_C_COMPANY_JOIN, c->is_ai);
2323 
2324  if (reinit) {
2325  this->ReInit();
2326  return;
2327  }
2328  }
2329 
2330  this->DrawWidgets();
2331  }
2332 
2333  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2334  {
2335  switch (widget) {
2336  case WID_C_FACE: {
2337  Dimension face_size = GetSpriteSize(SPR_GRADIENT);
2338  size->width = max(size->width, face_size.width);
2339  size->height = max(size->height, face_size.height);
2340  break;
2341  }
2342 
2344  Point offset;
2345  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2346  d.width -= offset.x;
2347  d.height -= offset.y;
2348  *size = maxdim(*size, d);
2349  break;
2350  }
2351 
2353  SetDParam(0, INT64_MAX); // Arguably the maximum company value
2354  size->width = GetStringBoundingBox(STR_COMPANY_VIEW_COMPANY_VALUE).width;
2355  break;
2356 
2358  SetDParamMaxValue(0, 5000); // Maximum number of vehicles
2359  for (uint i = 0; i < lengthof(_company_view_vehicle_count_strings); i++) {
2360  size->width = max(size->width, GetStringBoundingBox(_company_view_vehicle_count_strings[i]).width);
2361  }
2362  break;
2363 
2365  SetDParamMaxValue(0, UINT_MAX);
2366  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL).width);
2367  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD).width);
2368  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_WATER).width);
2369  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_STATION).width);
2370  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT).width);
2371  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_INFRASTRUCTURE_NONE).width);
2372  break;
2373 
2374  case WID_C_DESC_OWNERS: {
2375  const Company *c2;
2376 
2377  FOR_ALL_COMPANIES(c2) {
2378  SetDParamMaxValue(0, 75);
2379  SetDParam(1, c2->index);
2380 
2381  size->width = max(size->width, GetStringBoundingBox(STR_COMPANY_VIEW_SHARES_OWNED_BY).width);
2382  }
2383  break;
2384  }
2385 
2386 #ifdef ENABLE_NETWORK
2387  case WID_C_HAS_PASSWORD:
2388  *size = maxdim(*size, GetSpriteSize(SPR_LOCK));
2389  break;
2390 #endif /* ENABLE_NETWORK */
2391  }
2392  }
2393 
2394  virtual void DrawWidget(const Rect &r, int widget) const
2395  {
2396  const Company *c = Company::Get((CompanyID)this->window_number);
2397  switch (widget) {
2398  case WID_C_FACE:
2399  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2400  break;
2401 
2402  case WID_C_FACE_TITLE:
2403  SetDParam(0, c->index);
2404  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_COMPANY_VIEW_PRESIDENT_MANAGER_TITLE, TC_FROMSTRING, SA_HOR_CENTER);
2405  break;
2406 
2408  Point offset;
2409  Dimension d = GetSpriteSize(SPR_VEH_BUS_SW_VIEW, &offset);
2410  d.height -= offset.y;
2411  DrawSprite(SPR_VEH_BUS_SW_VIEW, COMPANY_SPRITE_COLOUR(c->index), r.left - offset.x, (r.top + r.bottom - d.height) / 2 - offset.y);
2412  break;
2413  }
2414 
2416  uint amounts[4];
2417  amounts[0] = c->group_all[VEH_TRAIN].num_vehicle;
2418  amounts[1] = c->group_all[VEH_ROAD].num_vehicle;
2419  amounts[2] = c->group_all[VEH_SHIP].num_vehicle;
2420  amounts[3] = c->group_all[VEH_AIRCRAFT].num_vehicle;
2421 
2422  int y = r.top;
2423  if (amounts[0] + amounts[1] + amounts[2] + amounts[3] == 0) {
2424  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_VEHICLES_NONE);
2425  } else {
2426  assert_compile(lengthof(amounts) == lengthof(_company_view_vehicle_count_strings));
2427 
2428  for (uint i = 0; i < lengthof(amounts); i++) {
2429  if (amounts[i] != 0) {
2430  SetDParam(0, amounts[i]);
2431  DrawString(r.left, r.right, y, _company_view_vehicle_count_strings[i]);
2432  y += FONT_HEIGHT_NORMAL;
2433  }
2434  }
2435  }
2436  break;
2437  }
2438 
2440  uint y = r.top;
2441 
2442  /* Collect rail and road counts. */
2443  uint rail_pieces = c->infrastructure.signal;
2444  uint road_pieces = 0;
2445  for (uint i = 0; i < lengthof(c->infrastructure.rail); i++) rail_pieces += c->infrastructure.rail[i];
2446  for (uint i = 0; i < lengthof(c->infrastructure.road); i++) road_pieces += c->infrastructure.road[i];
2447 
2448  if (rail_pieces == 0 && road_pieces == 0 && c->infrastructure.water == 0 && c->infrastructure.station == 0 && c->infrastructure.airport == 0) {
2449  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_NONE);
2450  } else {
2451  if (rail_pieces != 0) {
2452  SetDParam(0, rail_pieces);
2453  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_RAIL);
2454  y += FONT_HEIGHT_NORMAL;
2455  }
2456  if (road_pieces != 0) {
2457  SetDParam(0, road_pieces);
2458  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_ROAD);
2459  y += FONT_HEIGHT_NORMAL;
2460  }
2461  if (c->infrastructure.water != 0) {
2463  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_WATER);
2464  y += FONT_HEIGHT_NORMAL;
2465  }
2466  if (c->infrastructure.station != 0) {
2468  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_STATION);
2469  y += FONT_HEIGHT_NORMAL;
2470  }
2471  if (c->infrastructure.airport != 0) {
2473  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_INFRASTRUCTURE_AIRPORT);
2474  }
2475  }
2476 
2477  break;
2478  }
2479 
2480  case WID_C_DESC_OWNERS: {
2481  const Company *c2;
2482  uint y = r.top;
2483 
2484  FOR_ALL_COMPANIES(c2) {
2485  uint amt = GetAmountOwnedBy(c, c2->index);
2486  if (amt != 0) {
2487  SetDParam(0, amt * 25);
2488  SetDParam(1, c2->index);
2489 
2490  DrawString(r.left, r.right, y, STR_COMPANY_VIEW_SHARES_OWNED_BY);
2491  y += FONT_HEIGHT_NORMAL;
2492  }
2493  }
2494  break;
2495  }
2496 
2497 #ifdef ENABLE_NETWORK
2498  case WID_C_HAS_PASSWORD:
2500  DrawSprite(SPR_LOCK, PAL_NONE, r.left, r.top);
2501  }
2502  break;
2503 #endif /* ENABLE_NETWORK */
2504  }
2505  }
2506 
2507  virtual void SetStringParameters(int widget) const
2508  {
2509  switch (widget) {
2510  case WID_C_CAPTION:
2511  SetDParam(0, (CompanyID)this->window_number);
2512  SetDParam(1, (CompanyID)this->window_number);
2513  break;
2514 
2516  SetDParam(0, Company::Get((CompanyID)this->window_number)->inaugurated_year);
2517  break;
2518 
2520  SetDParam(0, CalculateCompanyValue(Company::Get((CompanyID)this->window_number)));
2521  break;
2522  }
2523  }
2524 
2525  virtual void OnClick(Point pt, int widget, int click_count)
2526  {
2527  switch (widget) {
2528  case WID_C_NEW_FACE: DoSelectCompanyManagerFace(this); break;
2529 
2530  case WID_C_COLOUR_SCHEME:
2531  ShowCompanyLiveryWindow((CompanyID)this->window_number, INVALID_GROUP);
2532  break;
2533 
2534  case WID_C_PRESIDENT_NAME:
2535  this->query_widget = WID_C_PRESIDENT_NAME;
2536  SetDParam(0, this->window_number);
2537  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);
2538  break;
2539 
2540  case WID_C_COMPANY_NAME:
2541  this->query_widget = WID_C_COMPANY_NAME;
2542  SetDParam(0, this->window_number);
2543  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);
2544  break;
2545 
2546  case WID_C_VIEW_HQ: {
2547  TileIndex tile = Company::Get((CompanyID)this->window_number)->location_of_HQ;
2548  if (_ctrl_pressed) {
2550  } else {
2551  ScrollMainWindowToTile(tile);
2552  }
2553  break;
2554  }
2555 
2556  case WID_C_BUILD_HQ:
2557  if ((byte)this->window_number != _local_company) return;
2558  if (this->IsWidgetLowered(WID_C_BUILD_HQ)) {
2560  this->RaiseButtons();
2561  break;
2562  }
2563  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2564  SetTileSelectSize(2, 2);
2565  this->LowerWidget(WID_C_BUILD_HQ);
2566  this->SetWidgetDirty(WID_C_BUILD_HQ);
2567  break;
2568 
2569  case WID_C_RELOCATE_HQ:
2570  if (this->IsWidgetLowered(WID_C_RELOCATE_HQ)) {
2572  this->RaiseButtons();
2573  break;
2574  }
2575  SetObjectToPlaceWnd(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, this);
2576  SetTileSelectSize(2, 2);
2577  this->LowerWidget(WID_C_RELOCATE_HQ);
2578  this->SetWidgetDirty(WID_C_RELOCATE_HQ);
2579  break;
2580 
2582  ShowCompanyInfrastructure((CompanyID)this->window_number);
2583  break;
2584 
2585  case WID_C_BUY_SHARE:
2586  DoCommandP(0, this->window_number, 0, CMD_BUY_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_25_SHARE_IN_THIS));
2587  break;
2588 
2589  case WID_C_SELL_SHARE:
2590  DoCommandP(0, this->window_number, 0, CMD_SELL_SHARE_IN_COMPANY | CMD_MSG(STR_ERROR_CAN_T_SELL_25_SHARE_IN));
2591  break;
2592 
2593 #ifdef ENABLE_NETWORK
2595  if (this->window_number == _local_company) ShowNetworkCompanyPasswordWindow(this);
2596  break;
2597 
2598  case WID_C_COMPANY_JOIN: {
2599  this->query_widget = WID_C_COMPANY_JOIN;
2600  CompanyID company = (CompanyID)this->window_number;
2601  if (_network_server) {
2604  } else if (NetworkCompanyIsPassworded(company)) {
2605  /* ask for the password */
2606  ShowQueryString(STR_EMPTY, STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION, NETWORK_PASSWORD_LENGTH, this, CS_ALPHANUMERAL, QSF_NONE);
2607  } else {
2608  /* just send the join command */
2609  NetworkClientRequestMove(company);
2610  }
2611  break;
2612  }
2613 #endif /* ENABLE_NETWORK */
2614  }
2615  }
2616 
2617  virtual void OnHundredthTick()
2618  {
2619  /* redraw the window every now and then */
2620  this->SetDirty();
2621  }
2622 
2623  virtual void OnPlaceObject(Point pt, TileIndex tile)
2624  {
2625  if (DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)) && !_shift_pressed) {
2627  this->RaiseButtons();
2628  }
2629  }
2630 
2631  virtual void OnPlaceObjectAbort()
2632  {
2633  this->RaiseButtons();
2634  }
2635 
2636  virtual void OnQueryTextFinished(char *str)
2637  {
2638  if (str == NULL) return;
2639 
2640  switch (this->query_widget) {
2641  default: NOT_REACHED();
2642 
2643  case WID_C_PRESIDENT_NAME:
2644  DoCommandP(0, 0, 0, CMD_RENAME_PRESIDENT | CMD_MSG(STR_ERROR_CAN_T_CHANGE_PRESIDENT), NULL, str);
2645  break;
2646 
2647  case WID_C_COMPANY_NAME:
2648  DoCommandP(0, 0, 0, CMD_RENAME_COMPANY | CMD_MSG(STR_ERROR_CAN_T_CHANGE_COMPANY_NAME), NULL, str);
2649  break;
2650 
2651 #ifdef ENABLE_NETWORK
2652  case WID_C_COMPANY_JOIN:
2653  NetworkClientRequestMove((CompanyID)this->window_number, str);
2654  break;
2655 #endif /* ENABLE_NETWORK */
2656  }
2657  }
2658 
2659 
2665  virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
2666  {
2667  if (this->window_number == _local_company) return;
2668 
2669  if (_settings_game.economy.allow_shares) { // Shares are allowed
2670  const Company *c = Company::Get(this->window_number);
2671 
2672  /* If all shares are owned by someone (none by nobody), disable buy button */
2673  this->SetWidgetDisabledState(WID_C_BUY_SHARE, GetAmountOwnedBy(c, INVALID_OWNER) == 0 ||
2674  /* Only 25% left to buy. If the company is human, disable buying it up.. TODO issues! */
2675  (GetAmountOwnedBy(c, INVALID_OWNER) == 1 && !c->is_ai) ||
2676  /* Spectators cannot do anything of course */
2678 
2679  /* If the company doesn't own any shares, disable sell button */
2680  this->SetWidgetDisabledState(WID_C_SELL_SHARE, (GetAmountOwnedBy(c, _local_company) == 0) ||
2681  /* Spectators cannot do anything of course */
2683  } else { // Shares are not allowed, disable buy/sell buttons
2684  this->DisableWidget(WID_C_BUY_SHARE);
2685  this->DisableWidget(WID_C_SELL_SHARE);
2686  }
2687  }
2688 };
2689 
2690 static WindowDesc _company_desc(
2691  WDP_AUTO, "company", 0, 0,
2693  0,
2694  _nested_company_widgets, lengthof(_nested_company_widgets)
2695 );
2696 
2701 void ShowCompany(CompanyID company)
2702 {
2703  if (!Company::IsValidID(company)) return;
2704 
2705  AllocateWindowDescFront<CompanyWindow>(&_company_desc, company);
2706 }
2707 
2713 {
2714  SetWindowDirty(WC_COMPANY, company);
2716 }
2717 
2719  BuyCompanyWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
2720  {
2721  this->InitNested(window_number);
2722  }
2723 
2724  virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
2725  {
2726  switch (widget) {
2727  case WID_BC_FACE:
2728  *size = GetSpriteSize(SPR_GRADIENT);
2729  break;
2730 
2731  case WID_BC_QUESTION:
2732  const Company *c = Company::Get((CompanyID)this->window_number);
2733  SetDParam(0, c->index);
2734  SetDParam(1, c->bankrupt_value);
2735  size->height = GetStringHeight(STR_BUY_COMPANY_MESSAGE, size->width);
2736  break;
2737  }
2738  }
2739 
2740  virtual void SetStringParameters(int widget) const
2741  {
2742  switch (widget) {
2743  case WID_BC_CAPTION:
2744  SetDParam(0, STR_COMPANY_NAME);
2745  SetDParam(1, Company::Get((CompanyID)this->window_number)->index);
2746  break;
2747  }
2748  }
2749 
2750  virtual void DrawWidget(const Rect &r, int widget) const
2751  {
2752  switch (widget) {
2753  case WID_BC_FACE: {
2754  const Company *c = Company::Get((CompanyID)this->window_number);
2755  DrawCompanyManagerFace(c->face, c->colour, r.left, r.top);
2756  break;
2757  }
2758 
2759  case WID_BC_QUESTION: {
2760  const Company *c = Company::Get((CompanyID)this->window_number);
2761  SetDParam(0, c->index);
2762  SetDParam(1, c->bankrupt_value);
2763  DrawStringMultiLine(r.left, r.right, r.top, r.bottom, STR_BUY_COMPANY_MESSAGE, TC_FROMSTRING, SA_CENTER);
2764  break;
2765  }
2766  }
2767  }
2768 
2769  virtual void OnClick(Point pt, int widget, int click_count)
2770  {
2771  switch (widget) {
2772  case WID_BC_NO:
2773  delete this;
2774  break;
2775 
2776  case WID_BC_YES:
2777  DoCommandP(0, this->window_number, 0, CMD_BUY_COMPANY | CMD_MSG(STR_ERROR_CAN_T_BUY_COMPANY));
2778  break;
2779  }
2780  }
2781 };
2782 
2783 static const NWidgetPart _nested_buy_company_widgets[] = {
2785  NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
2786  NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE, WID_BC_CAPTION), SetDataTip(STR_ERROR_MESSAGE_CAPTION_OTHER_COMPANY, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
2787  EndContainer(),
2788  NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
2789  NWidget(NWID_VERTICAL), SetPIP(8, 8, 8),
2790  NWidget(NWID_HORIZONTAL), SetPIP(8, 10, 8),
2791  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_FACE), SetFill(0, 1),
2792  NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BC_QUESTION), SetMinimalSize(240, 0), SetFill(1, 1),
2793  EndContainer(),
2794  NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(100, 10, 100),
2795  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_NO), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
2796  NWidget(WWT_TEXTBTN, COLOUR_LIGHT_BLUE, WID_BC_YES), SetMinimalSize(60, 12), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
2797  EndContainer(),
2798  EndContainer(),
2799  EndContainer(),
2800 };
2801 
2802 static WindowDesc _buy_company_desc(
2803  WDP_AUTO, NULL, 0, 0,
2806  _nested_buy_company_widgets, lengthof(_nested_buy_company_widgets)
2807 );
2808 
2814 {
2815  AllocateWindowDescFront<BuyCompanyWindow>(&_buy_company_desc, company);
2816 }
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:3199
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:271
No button.
bool _ctrl_pressed
Is Ctrl pressed?
Definition: gfx.cpp:36
Text about tie and earring.
Selection of maxloan column.
Spacer for dropdown.
static NWidgetPart SetMatrixDataTip(uint8 cols, uint8 rows, StringID tip)
Widget part function for setting the data and tooltip of WWT_MATRIX widgets.
Definition: widget_type.h:1032
static NWidgetPart SetPadding(uint8 top, uint8 right, uint8 bottom, uint8 left)
Widget part function for setting additional space around a widget.
Definition: widget_type.h:1046
Hair right.
void ShowErrorMessage(StringID summary_msg, StringID detailed_msg, WarningLevel wl, int x=0, int y=0, const GRFFile *textref_stack_grffile=NULL, uint textref_stack_size=0, const uint32 *textref_stack=NULL)
Display an error message in a window.
Definition: error_gui.cpp:378
Bottom offset of the text of the frame.
Definition: window_gui.h:75
Female button in the advanced view.
enable the &#39;Default&#39; button ("\0" is returned)
Definition: textbuf_gui.h:23
Aircraft vehicle type.
Definition: vehicle_type.h: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:3015
Count of total.
Matrix scrollbar.
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition: sprites.h:1543
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:105
void SelectDisplayPlanes(bool advanced)
Select planes to display to the user with the NWID_SELECTION widgets WID_SCMF_SEL_LOADSAVE, WID_SCMF_SEL_MALEFEMALE, and WID_SCMF_SEL_PARTS.
Decrease loan..
Count of station.
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
Vertical container.
Definition: widget_type.h:77
Property costs.
Definition: economy_type.h:157
Selection to display the male/female buttons in the simple view.
static NWidgetPart EndContainer()
Widget part function for denoting the end of a container (horizontal, vertical, WWT_FRAME, WWT_INSET, or WWT_PANEL).
Definition: widget_type.h:999
Display the build button.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
change the president name
Definition: command_type.h:246
Functions related to zooming.
int shown_plane
Plane being displayed (for NWID_SELECTION only).
Definition: widget_type.h:420
uint current_x
Current horizontal size (after resizing).
Definition: widget_type.h:174
Panel about &#39;Relocate HQ&#39;.
#define endof(x)
Get the end element of an fixed size array.
Definition: stdafx.h:403
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:3075
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:307
Other expenses.
Definition: economy_type.h:163
Road vehicle is a tram/light rail vehicle.
Definition: engine_type.h:154
Eyebrows right.
static void DrawYearColumn(const Rect &r, int year, const Money(*tbl)[EXPENSES_END])
Draw a column with prices.
Functions related to tile highlights.
uint total_width
String width of the total cost line.
Save face.
Owner
Enum for all companies/owners.
Definition: company_type.h:20
Window functions not directly related to making/drawing windows.
virtual void OnPaint()
The window must be repainted.
GRFLoadedFeatures _loaded_newgrf_features
Indicates which are the newgrf features currently loaded ingame.
Definition: newgrf.cpp:77
Find a place automatically.
Definition: window_gui.h:156
Functions related to water (management)
(Toggle) Button with image
Definition: widget_type.h:52
virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
Update size and resize step of a widget in the window.
static const NWidgetPart _nested_select_company_manager_face_widgets[]
Nested widget description for the company manager face selection dialog.
Male button in the advanced view.
Button to change president name.
Nose right.
Text about ethnicity european.
Stacked widgets, only one visible at a time (eg in a panel with tabs).
Definition: widget_type.h:80
GUI functions that shouldn&#39;t be here.
static Money RailMaintenanceCost(RailType railtype, uint32 num, uint32 total_num)
Calculates the maintenance cost of a number of track bits.
Definition: rail.h: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:1241
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.