Rearrange conditionals in FreeTrainTrackReservation
[openttd/fttd.git] / src / engine_gui.cpp
blob6ee47692d43c71ba7eabf2928899c06b19247f56
1 /* $Id$ */
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 */
10 /** @file engine_gui.cpp GUI to show engine related information. */
12 #include "stdafx.h"
13 #include "window_gui.h"
14 #include "engine_base.h"
15 #include "command_func.h"
16 #include "strings_func.h"
17 #include "engine_gui.h"
18 #include "articulated_vehicles.h"
19 #include "vehicle_func.h"
20 #include "company_func.h"
21 #include "rail.h"
22 #include "settings_type.h"
24 #include "widgets/engine_widget.h"
26 #include "table/strings.h"
28 /**
29 * Return the category of an engine.
30 * @param engine Engine to examine.
31 * @return String describing the category ("road veh", "train". "airplane", or "ship") of the engine.
33 StringID GetEngineCategoryName(EngineID engine)
35 const Engine *e = Engine::Get(engine);
36 switch (e->type) {
37 default: NOT_REACHED();
38 case VEH_ROAD: return STR_ENGINE_PREVIEW_ROAD_VEHICLE;
39 case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
40 case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
41 case VEH_TRAIN:
42 return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
46 static const NWidgetPart _nested_engine_preview_widgets[] = {
47 NWidget(NWID_HORIZONTAL),
48 NWidget(WWT_CLOSEBOX, COLOUR_LIGHT_BLUE),
49 NWidget(WWT_CAPTION, COLOUR_LIGHT_BLUE), SetDataTip(STR_ENGINE_PREVIEW_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
50 EndContainer(),
51 NWidget(WWT_PANEL, COLOUR_LIGHT_BLUE),
52 NWidget(WWT_EMPTY, INVALID_COLOUR, WID_EP_QUESTION), SetMinimalSize(300, 0), SetPadding(8, 8, 8, 8), SetFill(1, 0),
53 NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), SetPIP(85, 10, 85),
54 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_NO), SetDataTip(STR_QUIT_NO, STR_NULL), SetFill(1, 0),
55 NWidget(WWT_PUSHTXTBTN, COLOUR_LIGHT_BLUE, WID_EP_YES), SetDataTip(STR_QUIT_YES, STR_NULL), SetFill(1, 0),
56 EndContainer(),
57 NWidget(NWID_SPACER), SetMinimalSize(0, 8),
58 EndContainer(),
61 struct EnginePreviewWindow : Window {
62 static const int VEHICLE_SPACE = 40; // The space to show the vehicle image
64 EnginePreviewWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
66 this->InitNested(window_number);
68 /* There is no way to recover the window; so disallow closure via DEL; unless SHIFT+DEL */
69 this->flags |= WF_STICKY;
72 virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize)
74 if (widget != WID_EP_QUESTION) return;
76 EngineID engine = this->window_number;
77 SetDParam(0, GetEngineCategoryName(engine));
78 size->height = GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, size->width) + WD_PAR_VSEP_WIDE + FONT_HEIGHT_NORMAL + VEHICLE_SPACE;
79 SetDParam(0, engine);
80 size->height += GetStringHeight(GetEngineInfoString(engine), size->width);
83 virtual void DrawWidget(const Rect &r, int widget) const
85 if (widget != WID_EP_QUESTION) return;
87 EngineID engine = this->window_number;
88 SetDParam(0, GetEngineCategoryName(engine));
89 int y = r.top + GetStringHeight(STR_ENGINE_PREVIEW_MESSAGE, r.right - r.top + 1);
90 y = DrawStringMultiLine(r.left, r.right, r.top, y, STR_ENGINE_PREVIEW_MESSAGE, TC_FROMSTRING, SA_CENTER) + WD_PAR_VSEP_WIDE;
92 SetDParam(0, engine);
93 DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_ENGINE_NAME, TC_BLACK, SA_HOR_CENTER);
94 y += FONT_HEIGHT_NORMAL;
96 DrawVehicleEngine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, this->width >> 1, y + VEHICLE_SPACE / 2, engine, GetEnginePalette(engine, _local_company), EIT_PREVIEW);
98 y += VEHICLE_SPACE;
99 DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, r.bottom, GetEngineInfoString(engine), TC_FROMSTRING, SA_CENTER);
102 virtual void OnClick(Point pt, int widget, int click_count)
104 switch (widget) {
105 case WID_EP_YES:
106 DoCommandP(0, this->window_number, 0, CMD_WANT_ENGINE_PREVIEW);
107 /* FALL THROUGH */
108 case WID_EP_NO:
109 delete this;
110 break;
114 virtual void OnInvalidateData(int data = 0, bool gui_scope = true)
116 if (!gui_scope) return;
118 EngineID engine = this->window_number;
119 if (Engine::Get(engine)->preview_company != _local_company) delete this;
123 static WindowDesc _engine_preview_desc(
124 WDP_CENTER, "engine_preview", 0, 0,
125 WC_ENGINE_PREVIEW, WC_NONE,
126 WDF_CONSTRUCTION,
127 _nested_engine_preview_widgets, lengthof(_nested_engine_preview_widgets)
131 void ShowEnginePreviewWindow(EngineID engine)
133 AllocateWindowDescFront<EnginePreviewWindow>(&_engine_preview_desc, engine);
137 * Get the capacity of an engine with articulated parts.
138 * @param engine The engine to get the capacity of.
139 * @return The capacity.
141 uint GetTotalCapacityOfArticulatedParts(EngineID engine)
143 uint total = 0;
145 CargoArray cap = GetCapacityOfArticulatedParts(engine);
146 for (CargoID c = 0; c < NUM_CARGO; c++) {
147 total += cap[c];
150 return total;
153 static StringID GetTrainEngineInfoString(const Engine *e)
155 SetDParam(0, e->GetCost());
156 SetDParam(2, e->GetDisplayMaxSpeed());
157 SetDParam(3, e->GetPower());
158 SetDParam(1, e->GetDisplayWeight());
159 SetDParam(7, e->GetDisplayMaxTractiveEffort());
161 SetDParam(4, e->GetRunningCost());
163 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
164 if (capacity != 0) {
165 SetDParam(5, e->GetDefaultCargoType());
166 SetDParam(6, capacity);
167 } else {
168 SetDParam(5, CT_INVALID);
170 return (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(e->u.rail.railtype)->acceleration_type != 2) ? STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE : STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER;
173 static StringID GetAircraftEngineInfoString(const Engine *e)
175 CargoID cargo = e->GetDefaultCargoType();
176 uint16 mail_capacity;
177 uint capacity = e->GetDisplayDefaultCapacity(&mail_capacity);
178 uint16 range = e->GetRange();
180 uint i = 0;
181 SetDParam(i++, e->GetCost());
182 SetDParam(i++, e->GetDisplayMaxSpeed());
183 if (range > 0) SetDParam(i++, range);
184 SetDParam(i++, cargo);
185 SetDParam(i++, capacity);
187 if (mail_capacity > 0) {
188 SetDParam(i++, CT_MAIL);
189 SetDParam(i++, mail_capacity);
190 SetDParam(i++, e->GetRunningCost());
191 return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_CAPACITY_RUNCOST;
192 } else {
193 SetDParam(i++, e->GetRunningCost());
194 return range > 0 ? STR_ENGINE_PREVIEW_COST_MAX_SPEED_RANGE_CAPACITY_RUNCOST : STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
198 static StringID GetRoadVehEngineInfoString(const Engine *e)
200 if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) {
201 SetDParam(0, e->GetCost());
202 SetDParam(1, e->GetDisplayMaxSpeed());
203 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
204 if (capacity != 0) {
205 SetDParam(2, e->GetDefaultCargoType());
206 SetDParam(3, capacity);
207 } else {
208 SetDParam(2, CT_INVALID);
210 SetDParam(4, e->GetRunningCost());
211 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
212 } else {
213 SetDParam(0, e->GetCost());
214 SetDParam(2, e->GetDisplayMaxSpeed());
215 SetDParam(3, e->GetPower());
216 SetDParam(1, e->GetDisplayWeight());
217 SetDParam(7, e->GetDisplayMaxTractiveEffort());
219 SetDParam(4, e->GetRunningCost());
221 uint capacity = GetTotalCapacityOfArticulatedParts(e->index);
222 if (capacity != 0) {
223 SetDParam(5, e->GetDefaultCargoType());
224 SetDParam(6, capacity);
225 } else {
226 SetDParam(5, CT_INVALID);
228 return STR_ENGINE_PREVIEW_COST_WEIGHT_SPEED_POWER_MAX_TE;
232 static StringID GetShipEngineInfoString(const Engine *e)
234 SetDParam(0, e->GetCost());
235 SetDParam(1, e->GetDisplayMaxSpeed());
236 SetDParam(2, e->GetDefaultCargoType());
237 SetDParam(3, e->GetDisplayDefaultCapacity());
238 SetDParam(4, e->GetRunningCost());
239 return STR_ENGINE_PREVIEW_COST_MAX_SPEED_CAPACITY_RUNCOST;
244 * Get a multi-line string with some technical data, describing the engine.
245 * @param engine Engine to describe.
246 * @return String describing the engine.
247 * @post \c DParam array is set up for printing the string.
249 StringID GetEngineInfoString(EngineID engine)
251 const Engine *e = Engine::Get(engine);
253 switch (e->type) {
254 case VEH_TRAIN:
255 return GetTrainEngineInfoString(e);
257 case VEH_ROAD:
258 return GetRoadVehEngineInfoString(e);
260 case VEH_SHIP:
261 return GetShipEngineInfoString(e);
263 case VEH_AIRCRAFT:
264 return GetAircraftEngineInfoString(e);
266 default: NOT_REACHED();
271 * Draw an engine.
272 * @param left Minimum horizontal position to use for drawing the engine
273 * @param right Maximum horizontal position to use for drawing the engine
274 * @param preferred_x Horizontal position to use for drawing the engine.
275 * @param y Vertical position to use for drawing the engine.
276 * @param engine Engine to draw.
277 * @param pal Palette to use for drawing.
279 void DrawVehicleEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
281 const Engine *e = Engine::Get(engine);
283 switch (e->type) {
284 case VEH_TRAIN:
285 DrawTrainEngine(left, right, preferred_x, y, engine, pal, image_type);
286 break;
288 case VEH_ROAD:
289 DrawRoadVehEngine(left, right, preferred_x, y, engine, pal, image_type);
290 break;
292 case VEH_SHIP:
293 DrawShipEngine(left, right, preferred_x, y, engine, pal, image_type);
294 break;
296 case VEH_AIRCRAFT:
297 DrawAircraftEngine(left, right, preferred_x, y, engine, pal, image_type);
298 break;
300 default: NOT_REACHED();
305 * Sort all items using quick sort and given 'CompareItems' function
306 * @param el list to be sorted
307 * @param compare function for evaluation of the quicksort
309 void EngList_Sort(GUIEngineList *el, EngList_SortTypeFunction compare)
311 uint size = el->Length();
312 /* out-of-bounds access at the next line for size == 0 (even with operator[] at some systems)
313 * generally, do not sort if there are less than 2 items */
314 if (size < 2) return;
315 QSortT(el->Begin(), size, compare);
319 * Sort selected range of items (on indices @ <begin, begin+num_items-1>)
320 * @param el list to be sorted
321 * @param compare function for evaluation of the quicksort
322 * @param begin start of sorting
323 * @param num_items count of items to be sorted
325 void EngList_SortPartial(GUIEngineList *el, EngList_SortTypeFunction compare, uint begin, uint num_items)
327 if (num_items < 2) return;
328 assert(begin < el->Length());
329 assert(begin + num_items <= el->Length());
330 QSortT(el->Get(begin), num_items, compare);