4 //#include "tbtr_mygui.h"
10 #include "command_func.h"
11 #include "vehicle_gui.h"
12 #include "newgrf_engine.h"
15 #include "strings_func.h"
16 #include "window_func.h"
17 #include "autoreplace_func.h"
18 #include "company_func.h"
19 #include "engine_base.h"
20 #include "window_gui.h"
21 #include "viewport_func.h"
22 #include "tilehighlight_func.h"
23 #include "engine_gui.h"
24 #include "settings_func.h"
25 #include "core/geometry_func.hpp"
27 #include "network/network.h"
28 #include "zoom_func.h"
30 #include "table/sprites.h"
31 #include "table/strings.h"
33 // test creating pool -> creating vehicles
34 #include "core/pool_func.hpp"
36 #include "vehicle_gui_base.h"
37 #include "vehicle_base.h"
39 #include "vehicle_func.h"
43 #include "engine_func.h"
45 // drawing the vehicle length based on occupied tiles
46 #include "spritecache.h"
48 #include "tbtr_template_gui_main.h"
49 #include "tbtr_template_gui_create.h"
50 #include "tbtr_template_vehicle.h"
51 //#include "tbtr_template_vehicle_func.h"
54 typedef GUIList
<const Group
*> GUIGroupList
;
57 /* template creation */
58 void ShowTemplateCreationWindow(TileIndex
);
59 void ShowTestWindow();
61 enum TemplateReplaceWindowWidgets
{
64 TRW_WIDGET_INSET_GROUPS
,
65 TRW_WIDGET_TOP_MATRIX
,
66 TRW_WIDGET_TOP_SCROLLBAR
,
68 TRW_WIDGET_INSET_TEMPLATES
,
69 TRW_WIDGET_BOTTOM_MATRIX
,
70 TRW_WIDGET_MIDDLE_SCROLLBAR
,
71 TRW_WIDGET_BOTTOM_SCROLLBAR
,
73 TRW_WIDGET_TMPL_INFO_INSET
,
74 TRW_WIDGET_TMPL_INFO_PANEL
,
76 TRW_WIDGET_TMPL_PRE_BUTTON_FLUFF
,
78 TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE
,
79 TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP
,
80 TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT
,
81 TRW_WIDGET_TMPL_BUTTONS_CONFIG_RIGHTPANEL
,
83 TRW_WIDGET_TMPL_BUTTONS_DEFINE
,
84 TRW_WIDGET_TMPL_BUTTONS_EDIT
,
85 TRW_WIDGET_TMPL_BUTTONS_CLONE
,
86 TRW_WIDGET_TMPL_BUTTONS_DELETE
,
87 TRW_WIDGET_TMPL_BUTTONS_EDIT_RIGHTPANEL
,
89 TRW_WIDGET_TITLE_INFO_GROUP
,
90 TRW_WIDGET_TITLE_INFO_TEMPLATE
,
92 TRW_WIDGET_INFO_GROUP
,
93 TRW_WIDGET_INFO_TEMPLATE
,
95 TRW_WIDGET_TMPL_BUTTONS_SPACER
,
98 TRW_WIDGET_TRAIN_FLUFF_LEFT
,
99 TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
,
100 TRW_WIDGET_TRAIN_FLUFF_RIGHT
,
103 TRW_WIDGET_SEL_TMPL_DISPLAY_CREATE
,
107 static const NWidgetPart _widgets
[] = {
109 NWidget(NWID_HORIZONTAL
),
110 NWidget(WWT_CLOSEBOX
, COLOUR_GREY
),
111 NWidget(WWT_CAPTION
, COLOUR_GREY
, TRW_CAPTION
), SetDataTip(STR_TMPL_RPL_TITLE
, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS
),
112 NWidget(WWT_SHADEBOX
, COLOUR_GREY
),
113 NWidget(WWT_DEFSIZEBOX
, COLOUR_GREY
),
114 NWidget(WWT_STICKYBOX
, COLOUR_GREY
),
117 NWidget(NWID_VERTICAL
),
118 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_INSET_GROUPS
), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP
+ WD_DROPDOWNTEXT_BOTTOM
), SetResize(1, 0), EndContainer(),
119 NWidget(NWID_HORIZONTAL
),
120 NWidget(WWT_MATRIX
, COLOUR_GREY
, TRW_WIDGET_TOP_MATRIX
), SetMinimalSize(216, 0), SetFill(1, 1), SetDataTip(0x1, STR_REPLACE_HELP_LEFT_ARRAY
), SetResize(1, 0), SetScrollbar(TRW_WIDGET_TOP_SCROLLBAR
),
121 NWidget(NWID_VSCROLLBAR
, COLOUR_GREY
, TRW_WIDGET_TOP_SCROLLBAR
),
125 NWidget(NWID_VERTICAL
),
126 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_INSET_TEMPLATES
), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP
+ WD_DROPDOWNTEXT_BOTTOM
), SetResize(1, 0), EndContainer(),
127 NWidget(NWID_HORIZONTAL
),
128 NWidget(WWT_MATRIX
, COLOUR_GREY
, TRW_WIDGET_BOTTOM_MATRIX
), SetMinimalSize(216, 0), SetFill(1, 1), SetDataTip(0x1, STR_REPLACE_HELP_RIGHT_ARRAY
), SetResize(1, 1), SetScrollbar(TRW_WIDGET_MIDDLE_SCROLLBAR
),
129 NWidget(NWID_VSCROLLBAR
, COLOUR_GREY
, TRW_WIDGET_MIDDLE_SCROLLBAR
),
133 NWidget(NWID_VERTICAL
),
134 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TMPL_INFO_INSET
), SetMinimalTextLines(1, WD_DROPDOWNTEXT_TOP
+ WD_DROPDOWNTEXT_BOTTOM
), SetResize(1,0), EndContainer(),
135 NWidget(NWID_HORIZONTAL
),
136 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TMPL_INFO_PANEL
), SetMinimalSize(216,120), SetResize(1,0), SetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR
), EndContainer(),
137 NWidget(NWID_VSCROLLBAR
, COLOUR_GREY
, TRW_WIDGET_BOTTOM_SCROLLBAR
),
141 NWidget(NWID_VERTICAL
),
143 NWidget(WWT_INSET
, COLOUR_GREY
, TRW_WIDGET_TMPL_PRE_BUTTON_FLUFF
), SetMinimalSize(139, 12), SetResize(1,0), EndContainer(),
145 NWidget(NWID_HORIZONTAL
),
146 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE
), SetMinimalSize(150,12), SetResize(0,0), SetDataTip(STR_TMPL_SET_USEDEPOT
, STR_TMPL_SET_USEDEPOT_TIP
),
147 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP
), SetMinimalSize(150,12), SetResize(0,0), SetDataTip(STR_TMPL_SET_KEEPREMAINDERS
, STR_TMPL_SET_KEEPREMAINDERS_TIP
),
148 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT
), SetMinimalSize(150,12), SetResize(0,0), SetDataTip(STR_TMPL_SET_REFIT
, STR_TMPL_SET_REFIT_TIP
),
149 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_CONFIG_RIGHTPANEL
), SetMinimalSize(12,12), SetResize(1,0), EndContainer(),
152 NWidget(NWID_HORIZONTAL
),
153 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_DEFINE
), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DEFINE_TEMPLATE
, STR_TMPL_DEFINE_TEMPLATE
),
154 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_EDIT
), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_EDIT_TEMPLATE
, STR_TMPL_EDIT_TEMPLATE
),
155 NWidget(WWT_TEXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_CLONE
), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_CREATE_CLONE_VEH
, STR_TMPL_CREATE_CLONE_VEH
),
156 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_DELETE
), SetMinimalSize(75,12), SetResize(0,0), SetDataTip(STR_TMPL_DELETE_TEMPLATE
, STR_TMPL_DELETE_TEMPLATE
),
157 /*NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, TRW_WIDGET_TMPL_BUTTONS_RPLALL), SetMinimalSize(150,12), SetResize(0,0), SetDataTip(STR_TMPL_RPL_ALL_TMPL, STR_TMPL_RPL_ALL_TMPL),*/
158 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TMPL_BUTTONS_EDIT_RIGHTPANEL
), SetMinimalSize(50,12), SetResize(1,0), EndContainer(),
161 // Start/Stop buttons
162 NWidget(NWID_HORIZONTAL
),
163 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_START
), SetMinimalSize(150, 12), SetDataTip(STR_TMPL_RPL_START
, STR_REPLACE_ENGINE_WAGON_SELECT_HELP
),
164 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TRAIN_FLUFF_LEFT
), SetMinimalSize(15, 12), EndContainer(),
165 NWidget(WWT_DROPDOWN
, COLOUR_GREY
, TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
), SetMinimalSize(150, 12), SetDataTip(0x0, STR_REPLACE_HELP_RAILTYPE
), SetResize(1, 0),
166 NWidget(WWT_PANEL
, COLOUR_GREY
, TRW_WIDGET_TRAIN_FLUFF_RIGHT
), SetMinimalSize(16, 12), EndContainer(),
167 NWidget(WWT_PUSHTXTBTN
, COLOUR_GREY
, TRW_WIDGET_STOP
), SetMinimalSize(150, 12), SetDataTip(STR_TMPL_RPL_STOP
, STR_REPLACE_REMOVE_WAGON_HELP
),
168 NWidget(WWT_RESIZEBOX
, COLOUR_GREY
),
172 static WindowDesc
_replace_rail_vehicle_desc(
174 "template replace window",
177 WC_NONE
, // parent window class
179 _widgets
, lengthof(_widgets
)
182 class TemplateReplaceWindow
: public Window
{
185 GUIGroupList groups
; ///< List of groups
186 byte unitnumber_digits
;
188 SmallVector
<int, 16> indents
; ///< Indentation levels
191 short matrixContentLeftMargin
;
193 int details_height
; ///< Minimal needed height of the details panels (found so far).
194 RailType sel_railtype
; ///< Type of rail tracks selected.
195 Scrollbar
*vscroll
[3];
196 // listing/sorting continued
197 GUITemplateList templates
;
198 GUITemplateList::SortFunction
**template_sorter_funcs
;
200 short selected_template_index
;
201 short selected_group_index
;
206 TemplateReplaceWindow(WindowDesc
*wdesc
, byte dig
, int step_h
) : Window(wdesc
)
209 templates
.SetSortFuncs(this->template_sorter_funcs
);
211 // From BaseVehicleListWindow
212 this->unitnumber_digits
= dig
;
214 /* Find the most used vehicle type, which is usually
215 * better than 'just' the first/previous vehicle type. */
216 uint type_count
[RAILTYPE_END
];
217 memset(type_count
, 0, sizeof(type_count
));
220 FOR_ALL_ENGINES_OF_TYPE(e
, VEH_TRAIN
) {
221 if (e
->u
.rail
.railveh_type
== RAILVEH_WAGON
) continue;
222 type_count
[e
->u
.rail
.railtype
] += GetGroupNumEngines(_local_company
, ALL_GROUP
, e
->index
);
225 this->sel_railtype
= INVALID_RAILTYPE
;
227 this->details_height
= 10 * FONT_HEIGHT_NORMAL
+ WD_FRAMERECT_TOP
+ WD_FRAMERECT_BOTTOM
;
229 this->line_height
= step_h
;
231 this->CreateNestedTree(wdesc
!= nullptr);
232 this->vscroll
[0] = this->GetScrollbar(TRW_WIDGET_TOP_SCROLLBAR
);
233 this->vscroll
[1] = this->GetScrollbar(TRW_WIDGET_MIDDLE_SCROLLBAR
);
234 this->vscroll
[2] = this->GetScrollbar(TRW_WIDGET_BOTTOM_SCROLLBAR
);
235 this->FinishInitNested(VEH_TRAIN
);
237 this->owner
= _local_company
;
239 this->groups
.ForceRebuild();
240 this->groups
.NeedResort();
241 this->BuildGroupList(_local_company
);
243 this->matrixContentLeftMargin
= 40;
244 this->selected_template_index
= -1;
245 this->selected_group_index
= -1;
247 this->UpdateButtonState();
249 this->editInProgress
= false;
251 //this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_RPLALL, _networking);
253 this->templates
.ForceRebuild();
255 BuildTemplateGuiList(&this->templates
, this->vscroll
[1], this->owner
, this->sel_railtype
);
258 ~TemplateReplaceWindow() {
259 DeleteWindowById(WC_CREATE_TEMPLATE
, this->window_number
);
262 virtual void UpdateWidgetSize(int widget
, Dimension
*size
, const Dimension
&padding
, Dimension
*fill
, Dimension
*resize
)
265 case TRW_WIDGET_TOP_MATRIX
:
266 resize
->height
= GetVehicleListHeight(VEH_TRAIN
, FONT_HEIGHT_NORMAL
+ WD_MATRIX_TOP
) / 2;
267 size
->height
= 8 * resize
->height
;
269 case TRW_WIDGET_BOTTOM_MATRIX
:
270 resize
->height
= GetVehicleListHeight(VEH_TRAIN
, FONT_HEIGHT_NORMAL
+ WD_MATRIX_TOP
);
271 size
->height
= 4 * resize
->height
;
273 case TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
: {
274 Dimension d
= {0, 0};
275 for (RailType rt
= RAILTYPE_BEGIN
; rt
!= RAILTYPE_END
; rt
++) {
276 const RailtypeInfo
*rti
= GetRailTypeInfo(rt
);
277 // Skip rail type if it has no label
278 if (rti
->label
== 0) continue;
279 d
= maxdim(d
, GetStringBoundingBox(rti
->strings
.replace_text
));
281 d
.width
+= padding
.width
;
282 d
.height
+= padding
.height
;
283 *size
= maxdim(*size
, d
);
287 size
->width
= ScaleGUITrad(size
->width
);
292 virtual void SetStringParameters(int widget
) const
296 SetDParam(0, STR_TMPL_RPL_TITLE
);
301 virtual void DrawWidget(const Rect
&r
, int widget
) const
304 case TRW_WIDGET_TOP_MATRIX
: {
305 DrawAllGroupsFunction(this->line_height
, r
);
308 case TRW_WIDGET_BOTTOM_MATRIX
: {
309 DrawTemplateList(this->line_height
, r
);
312 case TRW_WIDGET_TMPL_INFO_PANEL
: {
313 DrawTemplateInfo(this->line_height
, r
);
316 case TRW_WIDGET_INSET_GROUPS
: {
317 DrawString(r
.left
+ 2, r
.right
- 2, r
.top
+ 2, STR_TMPL_MAINGUI_DEFINEDGROUPS
);
320 case TRW_WIDGET_INSET_TEMPLATES
: {
321 DrawString(r
.left
+ 2, r
.right
- 2, r
.top
+ 2, STR_TMPL_AVAILABLE_TEMPLATES
);
324 case TRW_WIDGET_TMPL_INFO_INSET
: {
325 DrawString(r
.left
+ 2, r
.right
- 2, r
.top
+ 2, STR_TMPL_TEMPLATE_INFO
);
331 virtual void OnPaint()
333 BuildTemplateGuiList(&this->templates
, this->vscroll
[1], this->owner
, this->sel_railtype
);
335 this->BuildGroupList(_local_company
);
337 /* sets the colour of that art thing */
338 this->GetWidget
<NWidgetCore
>(TRW_WIDGET_TRAIN_FLUFF_LEFT
)->colour
= _company_colours
[_local_company
];
339 this->GetWidget
<NWidgetCore
>(TRW_WIDGET_TRAIN_FLUFF_RIGHT
)->colour
= _company_colours
[_local_company
];
341 /* Show the selected railtype in the pulldown menu */
342 this->GetWidget
<NWidgetCore
>(TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
)->widget_data
=
343 (sel_railtype
== INVALID_RAILTYPE
) ? STR_REPLACE_ALL_RAILTYPE
: GetRailTypeInfo(sel_railtype
)->strings
.replace_text
;
346 if ((this->selected_template_index
< 0) || (this->selected_template_index
>= (short)this->templates
.Length())) {
347 this->vscroll
[2]->SetCount(24);
349 const TemplateVehicle
*tmp
= this->templates
[this->selected_template_index
];
351 uint min_height
= 30;
353 CargoArray cargo_caps
;
354 short count_columns
= 0;
355 short max_columns
= 2;
357 for ( ; tmp
; tmp
=tmp
->Next()) {
358 cargo_caps
[tmp
->cargo_type
] += tmp
->cargo_cap
;
361 for (CargoID i
= 0; i
< NUM_CARGO
; ++i
) {
362 if ( cargo_caps
[i
] > 0 ) {
363 if (count_columns
% max_columns
== 0) {
364 height
+= this->line_height
/3;
371 min_height
= max(min_height
, height
);
372 this->vscroll
[2]->SetCount(min_height
);
378 virtual void OnClick(Point pt
, int widget
, int click_count
)
380 if ( this->editInProgress
) return;
383 case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE
: {
384 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length())) {
385 uint32 template_index
= ((this->templates
)[selected_template_index
])->index
;
387 DoCommandP(0, template_index
, 0, CMD_TOGGLE_REUSE_DEPOT_VEHICLES
, nullptr);
391 case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP
: {
392 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length())) {
393 uint32 template_index
= ((this->templates
)[selected_template_index
])->index
;
395 DoCommandP(0, template_index
, 0, CMD_TOGGLE_KEEP_REMAINING_VEHICLES
, nullptr);
399 case TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT
: {
400 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length())) {
401 uint32 template_index
= ((this->templates
)[selected_template_index
])->index
;
403 DoCommandP(0, template_index
, 0, CMD_TOGGLE_REFIT_AS_TEMPLATE
, nullptr);
407 case TRW_WIDGET_TMPL_BUTTONS_DEFINE
: {
408 editInProgress
= true;
409 ShowTemplateCreateWindow(0, &editInProgress
, this->line_height
);
413 case TRW_WIDGET_TMPL_BUTTONS_EDIT
: {
414 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length())) {
415 editInProgress
= true;
416 TemplateVehicle
*sel
= TemplateVehicle::Get(((this->templates
)[selected_template_index
])->index
);
417 ShowTemplateCreateWindow(sel
, &editInProgress
, this->line_height
);
422 case TRW_WIDGET_TMPL_BUTTONS_CLONE
: {
423 this->SetWidgetDirty(TRW_WIDGET_TMPL_BUTTONS_CLONE
);
424 this->ToggleWidgetLoweredState(TRW_WIDGET_TMPL_BUTTONS_CLONE
);
426 if (this->IsWidgetLowered(TRW_WIDGET_TMPL_BUTTONS_CLONE
)) {
427 static const CursorID clone_icon
= SPR_CURSOR_CLONE_TRAIN
;
428 SetObjectToPlaceWnd(clone_icon
, PAL_NONE
, HT_VEHICLE
, this);
430 ResetObjectToPlace();
434 case TRW_WIDGET_TMPL_BUTTONS_DELETE
:
435 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length()) && !editInProgress
) {
437 uint32 template_index
= ((this->templates
)[selected_template_index
])->index
;
439 bool succeeded
= DoCommandP(0, template_index
, 0, CMD_DELETE_TEMPLATE_VEHICLE
, nullptr);
442 BuildTemplateGuiList(&this->templates
, this->vscroll
[1], this->owner
, this->sel_railtype
);
443 selected_template_index
= -1;
447 //case TRW_WIDGET_TMPL_BUTTONS_RPLALL: {
448 // ShowTemplateReplaceAllGui();
451 case TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
: // Railtype selection dropdown menu
452 ShowDropDownList(this, GetRailTypeDropDownList(true, true), sel_railtype
, TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
);
455 case TRW_WIDGET_TOP_MATRIX
: {
456 uint16 newindex
= (uint16
)((pt
.y
- this->nested_array
[TRW_WIDGET_TOP_MATRIX
]->pos_y
) / (this->line_height
/2) ) + this->vscroll
[0]->GetPosition();
457 if ( newindex
== this->selected_group_index
|| newindex
>= this->groups
.Length() ) {
458 this->selected_group_index
= -1;
460 else if ((newindex
>= 0) && (newindex
< this->groups
.Length())) {
461 this->selected_group_index
= newindex
;
463 this->UpdateButtonState();
466 case TRW_WIDGET_BOTTOM_MATRIX
: {
467 uint16 newindex
= (uint16
)((pt
.y
- this->nested_array
[TRW_WIDGET_BOTTOM_MATRIX
]->pos_y
) / this->line_height
) + this->vscroll
[1]->GetPosition();
468 if ( newindex
== this->selected_template_index
|| newindex
>= templates
.Length() ) {
469 this->selected_template_index
= -1;
471 else if ((newindex
>= 0) && (newindex
< templates
.Length())) {
472 this->selected_template_index
= newindex
;
474 this->UpdateButtonState();
477 case TRW_WIDGET_START
: {
478 if ((this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length()) &&
479 (this->selected_group_index
>= 0) && (this->selected_group_index
< (short)this->groups
.Length())) {
480 uint32 tv_index
= ((this->templates
)[selected_template_index
])->index
;
481 int current_group_index
= (this->groups
)[this->selected_group_index
]->index
;
483 DoCommandP(0, current_group_index
, tv_index
, CMD_ISSUE_TEMPLATE_REPLACEMENT
, nullptr);
484 this->UpdateButtonState();
488 case TRW_WIDGET_STOP
:
489 if ((this->selected_group_index
< 0) || (this->selected_group_index
>= (short)this->groups
.Length()))
492 int current_group_index
= (this->groups
)[this->selected_group_index
]->index
;
494 DoCommandP(0, current_group_index
, 0, CMD_DELETE_TEMPLATE_REPLACEMENT
, nullptr);
495 this->UpdateButtonState();
501 virtual bool OnVehicleSelect(const Vehicle
*v
)
503 bool succeeded
= DoCommandP(0, v
->index
, 0, CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN
| CMD_MSG(STR_TMPL_CANT_CREATE
), nullptr);
505 if (!succeeded
) return false;
507 BuildTemplateGuiList(&this->templates
, vscroll
[1], _local_company
, this->sel_railtype
);
508 this->ToggleWidgetLoweredState(TRW_WIDGET_TMPL_BUTTONS_CLONE
);
509 ResetObjectToPlace();
515 virtual void OnPlaceObjectAbort()
517 this->RaiseButtons();
520 virtual void OnDropdownSelect(int widget
, int index
)
522 RailType temp
= (RailType
)index
;
523 if (temp
== this->sel_railtype
) return; // we didn't select a new one. No need to change anything
524 this->sel_railtype
= temp
;
525 /* Reset scrollbar positions */
526 this->vscroll
[0]->SetPosition(0);
527 this->vscroll
[1]->SetPosition(0);
528 BuildTemplateGuiList(&this->templates
, this->vscroll
[1], this->owner
, this->sel_railtype
);
532 virtual void OnResize()
535 NWidgetCore
*nwi
= this->GetWidget
<NWidgetCore
>(TRW_WIDGET_TOP_MATRIX
);
536 this->vscroll
[0]->SetCapacityFromWidget(this, TRW_WIDGET_TOP_MATRIX
);
537 nwi
->widget_data
= (this->vscroll
[0]->GetCapacity() << MAT_ROW_START
) + (1 << MAT_COL_START
);
539 NWidgetCore
*nwi2
= this->GetWidget
<NWidgetCore
>(TRW_WIDGET_BOTTOM_MATRIX
);
540 this->vscroll
[1]->SetCapacityFromWidget(this, TRW_WIDGET_BOTTOM_MATRIX
);
541 nwi2
->widget_data
= (this->vscroll
[1]->GetCapacity() << MAT_ROW_START
) + (1 << MAT_COL_START
);
543 NWidgetCore
*nwi3
= this->GetWidget
<NWidgetCore
>(TRW_WIDGET_TMPL_INFO_PANEL
);
544 this->vscroll
[2]->SetCapacity(nwi3
->current_y
);
547 virtual void OnInvalidateData(int data
= 0, bool gui_scope
= true)
549 this->groups
.ForceRebuild();
550 this->templates
.ForceRebuild();
551 this->UpdateButtonState();
555 /** For a given group (id) find the template that is issued for template replacement for this group and return this template's index
556 * from the gui list */
557 short FindTemplateIndexForGroup(short gid
) const
559 TemplateReplacement
*tr
= GetTemplateReplacementByGroupID(gid
);
563 for ( uint32 i
=0; i
<this->templates
.Length(); ++i
)
564 if ( templates
[i
]->index
== tr
->sel_template
)
569 void AddParents(GUIGroupList
*source
, GroupID parent
, int indent
)
571 for (const Group
**g
= source
->Begin(); g
!= source
->End(); g
++) {
572 if ((*g
)->parent
== parent
) {
573 *this->groups
.Append() = *g
;
574 *this->indents
.Append() = indent
;
575 AddParents(source
, (*g
)->index
, indent
+ 1);
580 /** Sort the groups by their name */
581 static int CDECL
GroupNameSorter(const Group
* const *a
, const Group
* const *b
)
583 static const Group
*last_group
[2] = { nullptr, nullptr };
584 static char last_name
[2][64] = { "", "" };
586 if (*a
!= last_group
[0]) {
588 SetDParam(0, (*a
)->index
);
589 GetString(last_name
[0], STR_GROUP_NAME
, lastof(last_name
[0]));
592 if (*b
!= last_group
[1]) {
594 SetDParam(0, (*b
)->index
);
595 GetString(last_name
[1], STR_GROUP_NAME
, lastof(last_name
[1]));
598 int r
= strnatcmp(last_name
[0], last_name
[1]); // Sort by name (natural sorting).
599 if (r
== 0) return (*a
)->index
- (*b
)->index
;
603 void BuildGroupList(Owner owner
)
605 if (!this->groups
.NeedRebuild()) return;
607 this->groups
.Clear();
608 this->indents
.Clear();
614 if (g
->owner
== owner
&& g
->vehicle_type
== VEH_TRAIN
) {
620 list
.Sort(&GroupNameSorter
);
622 AddParents(&list
, INVALID_GROUP
, 0);
624 this->groups
.Compact();
625 this->groups
.RebuildDone();
626 this->vscroll
[0]->SetCount(groups
.Length());
629 void DrawAllGroupsFunction(int line_height
, const Rect
&r
) const
631 int left
= r
.left
+ WD_MATRIX_LEFT
;
632 int right
= r
.right
- WD_MATRIX_RIGHT
;
634 int max
= min(this->vscroll
[0]->GetPosition() + this->vscroll
[0]->GetCapacity(), this->groups
.Length());
636 /* Then treat all groups defined by/for the current company */
637 for ( int i
=this->vscroll
[0]->GetPosition(); i
<max
; ++i
) {
638 const Group
*g
= (this->groups
)[i
];
639 short g_id
= g
->index
;
641 /* Fill the background of the current cell in a darker tone for the currently selected template */
642 if ( this->selected_group_index
== i
) {
643 GfxFillRect(r
.left
+ 1, y
, r
.right
, y
+ (this->line_height
) / 2, _colour_gradient
[COLOUR_GREY
][3]);
646 int text_y
= y
+ ScaleGUITrad(3);
649 StringID str
= STR_GROUP_NAME
;
650 DrawString(left
+ ScaleGUITrad(30 + this->indents
[i
] * 10), right
, text_y
, str
, TC_BLACK
);
652 /* Draw the template in use for this group, if there is one */
653 short template_in_use
= FindTemplateIndexForGroup(g_id
);
654 if ( template_in_use
>= 0 ) {
655 SetDParam(0, template_in_use
);
656 DrawString(right
- ScaleGUITrad(600), right
, text_y
, STR_TMPL_GROUP_USES_TEMPLATE
, TC_BLACK
, SA_HOR_CENTER
);
658 /* If there isn't a template applied from the current group, check if there is one for another rail type */
659 else if ( GetTemplateReplacementByGroupID(g_id
) ) {
660 DrawString(right
- ScaleGUITrad(600), right
, text_y
, STR_TMPL_TMPLRPL_EX_DIFF_RAILTYPE
, TC_SILVER
, SA_HOR_CENTER
);
663 /* Draw the number of trains that still need to be treated by the currently selected template replacement */
664 TemplateReplacement
*tr
= GetTemplateReplacementByGroupID(g_id
);
666 TemplateVehicle
*tv
= TemplateVehicle::Get(tr
->sel_template
);
667 int num_trains
= NumTrainsNeedTemplateReplacement(g_id
, tv
);
669 TextColour color
= TC_GREY
;
670 if ( num_trains
) color
= TC_BLACK
;
671 DrawString(left
, right
- ScaleGUITrad(16), text_y
, STR_TMPL_NUM_TRAINS_NEED_RPL
, color
, SA_RIGHT
);
673 if ( num_trains
) color
= TC_ORANGE
;
674 else color
= TC_GREY
;
675 SetDParam(0, num_trains
);
676 DrawString(left
, right
- ScaleGUITrad(4), text_y
, STR_JUST_INT
, color
, SA_RIGHT
);
683 void DrawTemplateList(int line_height
, const Rect
&r
) const
689 Scrollbar
*draw_vscroll
= vscroll
[1];
690 uint max
= min(draw_vscroll
->GetPosition() + draw_vscroll
->GetCapacity(), this->templates
.Length());
692 const TemplateVehicle
*v
;
693 for ( uint i
= draw_vscroll
->GetPosition(); i
< max
; ++i
) {
695 v
= (this->templates
)[i
];
697 /* Fill the background of the current cell in a darker tone for the currently selected template */
698 if ( this->selected_template_index
== (int32
)i
) {
699 GfxFillRect(left
+ 1, y
, right
, y
+ this->line_height
, _colour_gradient
[COLOUR_GREY
][3]);
702 /* Draw the template */
703 DrawTemplate(v
, left
+ ScaleGUITrad(36), right
- ScaleGUITrad(24), y
);
705 /* Draw a notification string for chains that are not runnable */
706 if ( v
->IsFreeWagonChain() ) {
707 DrawString(left
, right
- ScaleGUITrad(24), y
+ ScaleGUITrad(2), STR_TMPL_WARNING_FREE_WAGON
, TC_RED
, SA_RIGHT
);
710 /* Draw the template's length in tile-units */
711 SetDParam(0, v
->GetRealLength());
713 DrawString(left
, right
- ScaleGUITrad(4), y
+ ScaleGUITrad(2), STR_TINY_BLACK_DECIMAL
, TC_BLACK
, SA_RIGHT
);
715 int bottom_edge
= y
+ line_height
- FONT_HEIGHT_SMALL
- WD_FRAMERECT_BOTTOM
- ScaleGUITrad(4);
718 SetDParam(0, CalculateOverallTemplateCost(v
));
719 DrawString(left
+ ScaleGUITrad(35), right
, bottom_edge
, STR_TMPL_TEMPLATE_OVR_VALUE_notinyfont
, TC_BLUE
, SA_LEFT
);
721 /* Index of current template vehicle in the list of all templates for its company */
723 DrawString(left
+ ScaleGUITrad(5), left
+ ScaleGUITrad(25), y
+ ScaleGUITrad(2), STR_BLACK_INT
, TC_BLACK
, SA_RIGHT
);
725 /* Draw whether the current template is in use by any group */
726 if ( v
->NumGroupsUsingTemplate() > 0 ) {
727 DrawString(left
+ ScaleGUITrad(35), right
, bottom_edge
- FONT_HEIGHT_SMALL
- ScaleGUITrad(3),
728 STR_TMP_TEMPLATE_IN_USE
, TC_GREEN
, SA_LEFT
);
731 /* Draw information about template configuration settings */
733 if ( v
->IsSetReuseDepotVehicles() ) color
= TC_LIGHT_BLUE
;
734 else color
= TC_GREY
;
735 DrawString(right
- ScaleGUITrad(275), right
, bottom_edge
, STR_TMPL_CONFIG_USEDEPOT
, color
, SA_LEFT
);
737 if (v
->IsSetKeepRemainingVehicles()) color
= TC_LIGHT_BLUE
;
738 else color
= TC_GREY
;
739 DrawString(right
- ScaleGUITrad(175), right
, bottom_edge
, STR_TMPL_CONFIG_KEEPREMAINDERS
, color
, SA_LEFT
);
741 if (v
->IsSetRefitAsTemplate()) color
= TC_LIGHT_BLUE
;
742 else color
= TC_GREY
;
743 DrawString(right
- ScaleGUITrad(75), right
, bottom_edge
, STR_TMPL_CONFIG_REFIT
, color
, SA_LEFT
);
749 void DrawTemplateInfo(int line_height
, const Rect
&r
) const
751 if ((this->selected_template_index
< 0) || (this->selected_template_index
>= (short)this->templates
.Length()))
755 DrawPixelInfo tmp_dpi
, *old_dpi
;
757 if (!FillDrawPixelInfo(&tmp_dpi
, r
.left
, r
.top
, r
.right
- r
.left
, r
.bottom
- r
.top
))
763 const TemplateVehicle
*tmp
= this->templates
[this->selected_template_index
];
765 double tractive_effort_loaded
= tmp
->weight
* 17;
766 double power
= tmp
->power
* 746ll;
767 double max_te
= tmp
->max_te
;
768 uint16 loaded_max_speed
= min(tmp
->max_speed
, (tractive_effort_loaded
== 0 || tractive_effort_loaded
> max_te
) ? 0 : (3.6 * (power
/ tractive_effort_loaded
)));
770 /* Draw vehicle performance info */
771 SetDParam(0, tmp
->weight
);
772 SetDParam(1, tmp
->power
);
773 SetDParam(2, loaded_max_speed
);
774 SetDParam(3, tmp
->max_te
/ 1000);
775 DrawString(8, r
.right
, ScaleGUITrad(4) - this->vscroll
[2]->GetPosition(), STR_VEHICLE_INFO_LOADED_WEIGHT_POWER_MAX_SPEED_MAX_TE
);
777 /* Draw cargo summary */
778 short top
= ScaleGUITrad(30) - this->vscroll
[2]->GetPosition();
779 short left
= ScaleGUITrad(8);
780 short count_columns
= 0;
781 short max_columns
= 2;
783 CargoArray cargo_caps
;
784 for ( ; tmp
; tmp
=tmp
->Next() )
785 cargo_caps
[tmp
->cargo_type
] += tmp
->cargo_cap
;
787 for (CargoID i
= 0; i
< NUM_CARGO
; ++i
) {
788 if ( cargo_caps
[i
] > 0 ) {
791 SetDParam(1, cargo_caps
[i
]);
792 SetDParam(2, _settings_game
.vehicle
.freight_trains
);
793 DrawString(x
, r
.right
, top
, FreightWagonMult(i
) > 1 ? STR_TMPL_CARGO_SUMMARY_MULTI
: STR_TMPL_CARGO_SUMMARY
, TC_LIGHT_BLUE
, SA_LEFT
);
794 x
+= ScaleGUITrad(250);
795 if ( count_columns
% max_columns
== 0 ) {
797 top
+= this->line_height
/3;
805 void UpdateButtonState()
807 bool selected_ok
= (this->selected_template_index
>= 0) && (this->selected_template_index
< (short)this->templates
.Length());
808 bool group_ok
= (this->selected_group_index
>= 0) && (this->selected_group_index
< (short)this->groups
.Length());
812 const Group
*g
= (this->groups
)[this->selected_group_index
];
816 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_EDIT
, this->editInProgress
|| !selected_ok
);
817 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DELETE
, this->editInProgress
|| !selected_ok
);
818 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REUSE
, this->editInProgress
|| !selected_ok
);
819 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_KEEP
, this->editInProgress
|| !selected_ok
);
820 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CONFIGTMPL_REFIT
, this->editInProgress
|| !selected_ok
);
822 this->SetWidgetDisabledState(TRW_WIDGET_START
, this->editInProgress
|| !(selected_ok
&& group_ok
&& FindTemplateIndexForGroup(g_id
) != this->selected_template_index
));
823 this->SetWidgetDisabledState(TRW_WIDGET_STOP
, this->editInProgress
|| !(group_ok
&& GetTemplateReplacementByGroupID(g_id
) != nullptr));
825 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_DEFINE
, this->editInProgress
);
826 this->SetWidgetDisabledState(TRW_WIDGET_TMPL_BUTTONS_CLONE
, this->editInProgress
);
827 this->SetWidgetDisabledState(TRW_WIDGET_TRAIN_RAILTYPE_DROPDOWN
, this->editInProgress
);
831 void ShowTemplateReplaceWindow(byte dig
, int step_h
)
834 new TemplateReplaceWindow(&_replace_rail_vehicle_desc
, dig
, step_h
);