--- a/src/vehicle_gui.cpp Mon May 19 14:14:33 2008 +0000
+++ b/src/vehicle_gui.cpp Mon May 19 15:13:58 2008 +0000
@@ -40,20 +40,6 @@
#include "table/sprites.h"
#include "table/strings.h"
-struct vehicledetails_d {
- byte tab;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(vehicledetails_d));
-
-struct refit_d {
- int sel;
- struct RefitOption *cargo;
- struct RefitList *list;
- uint length;
- VehicleOrderID order;
-};
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(refit_d));
-
Sorting _sorting;
static bool _internal_sort_order; // descending/ascending
@@ -100,47 +86,6 @@
INVALID_STRING_ID
};
-/**
- * Set sort list flag for all vehicle list windows
- * @param sl_flag Sort list flag to set
- */
-static void SetVehicleListsFlag(SortListFlags sl_flag)
-{
- Window* const *wz;
-
- FOR_ALL_WINDOWS(wz) {
- Window *w = *wz;
-
- switch (w->window_class) {
- case WC_TRAINS_LIST:
- case WC_ROADVEH_LIST:
- case WC_SHIPS_LIST:
- case WC_AIRCRAFT_LIST:
- dynamic_cast<VehicleListBase*>(w)->vehicles.flags |= sl_flag;
- w->SetDirty();
- break;
-
- default: break;
- }
- }
-}
-
-/**
- * Rebuild all vehicle list windows
- */
-void RebuildVehicleLists()
-{
- SetVehicleListsFlag(VL_REBUILD);
-}
-
-/**
- * Resort all vehicle list windows
- */
-void ResortVehicleLists()
-{
- SetVehicleListsFlag(VL_RESORT);
-}
-
void BuildVehicleList(VehicleListBase *vl, PlayerID owner, uint16 index, uint16 window_type)
{
if (!(vl->vehicles.flags & VL_REBUILD)) return;
@@ -333,89 +278,141 @@
return selected;
}
-static void VehicleRefitWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- Vehicle *v = GetVehicle(w->window_number);
+struct RefitWindow : public Window {
+ int sel;
+ RefitOption *cargo;
+ RefitList *list;
+ uint length;
+ VehicleOrderID order;
- if (v->type == VEH_TRAIN) {
- uint length = CountVehiclesInChain(v);
+ RefitWindow(const WindowDesc *desc, const Vehicle *v, VehicleOrderID order) : Window(desc, v->index)
+ {
+ this->caption_color = v->owner;
+ this->vscroll.cap = 8;
+ this->resize.step_height = 14;
- if (length != WP(w, refit_d).length) {
- /* Consist length has changed, so rebuild the refit list */
- free(WP(w, refit_d).list->items);
- free(WP(w, refit_d).list);
- WP(w, refit_d).list = BuildRefitList(v);
- WP(w, refit_d).length = length;
+ this->order = order;
+ this->sel = -1;
+ this->list = BuildRefitList(v);
+ if (v->type == VEH_TRAIN) this->length = CountVehiclesInChain(v);
+ SetVScrollCount(this, this->list->num_lines);
+
+ switch (v->type) {
+ case VEH_TRAIN:
+ this->widget[3].tooltips = STR_RAIL_SELECT_TYPE_OF_CARGO_FOR;
+ this->widget[6].data = STR_RAIL_REFIT_VEHICLE;
+ this->widget[6].tooltips = STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED;
+ break;
+
+ case VEH_ROAD:
+ this->widget[3].tooltips = STR_ROAD_SELECT_TYPE_OF_CARGO_FOR;
+ this->widget[6].data = STR_REFIT_ROAD_VEHICLE;
+ this->widget[6].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED;
+ break;
+
+ case VEH_SHIP:
+ this->widget[3].tooltips = STR_983D_SELECT_TYPE_OF_CARGO_FOR;
+ this->widget[6].data = STR_983C_REFIT_SHIP;
+ this->widget[6].tooltips = STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED;
+ break;
+
+ case VEH_AIRCRAFT:
+ this->widget[3].tooltips = STR_A03E_SELECT_TYPE_OF_CARGO_FOR;
+ this->widget[6].data = STR_A03D_REFIT_AIRCRAFT;
+ this->widget[6].tooltips = STR_A03F_REFIT_AIRCRAFT_TO_CARRY;
+ break;
+
+ default: NOT_REACHED();
+ }
+
+ this->FindWindowPlacementAndResize(desc);
+ }
+
+ ~RefitWindow()
+ {
+ free(this->list->items);
+ free(this->list);
+ }
+
+ virtual void OnPaint()
+ {
+ Vehicle *v = GetVehicle(this->window_number);
+
+ if (v->type == VEH_TRAIN) {
+ uint length = CountVehiclesInChain(v);
+
+ if (length != this->length) {
+ /* Consist length has changed, so rebuild the refit list */
+ free(this->list->items);
+ free(this->list);
+ this->list = BuildRefitList(v);
+ this->length = length;
+ }
+ }
+
+ SetVScrollCount(this, this->list->num_lines);
+
+ SetDParam(0, v->index);
+ this->DrawWidgets();
+
+ this->cargo = DrawVehicleRefitWindow(this->list, this->sel, this->vscroll.pos, this->vscroll.cap, this->resize.step_height);
+
+ if (this->cargo != NULL) {
+ CommandCost cost;
+
+ cost = DoCommand(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8,
+ DC_QUERY_COST, GetCmdRefitVeh(v->type));
+
+ if (CmdSucceeded(cost)) {
+ SetDParam(0, this->cargo->cargo);
+ SetDParam(1, _returned_refit_capacity);
+ SetDParam(2, cost.GetCost());
+ DrawString(2, this->widget[5].top + 1, STR_9840_NEW_CAPACITY_COST_OF_REFIT, TC_FROMSTRING);
+ }
+ }
+ }
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ switch (widget) {
+ case 3: { // listbox
+ int y = pt.y - this->widget[3].top;
+ if (y >= 0) {
+ this->sel = (y / (int)this->resize.step_height) + this->vscroll.pos;
+ this->SetDirty();
}
+ break;
}
- SetVScrollCount(w, WP(w, refit_d).list->num_lines);
-
- SetDParam(0, v->index);
- DrawWindowWidgets(w);
-
- WP(w, refit_d).cargo = DrawVehicleRefitWindow(WP(w, refit_d).list, WP(w, refit_d).sel, w->vscroll.pos, w->vscroll.cap, w->resize.step_height);
-
- if (WP(w, refit_d).cargo != NULL) {
- CommandCost cost;
-
- cost = DoCommand(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8,
- DC_QUERY_COST, GetCmdRefitVeh(GetVehicle(w->window_number)->type));
+ case 6: // refit button
+ if (this->cargo != NULL) {
+ const Vehicle *v = GetVehicle(this->window_number);
- if (CmdSucceeded(cost)) {
- SetDParam(0, WP(w, refit_d).cargo->cargo);
- SetDParam(1, _returned_refit_capacity);
- SetDParam(2, cost.GetCost());
- DrawString(2, w->widget[5].top + 1, STR_9840_NEW_CAPACITY_COST_OF_REFIT, TC_FROMSTRING);
- }
- }
- } break;
+ if (this->order == INVALID_VEH_ORDER_ID) {
+ int command = 0;
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 3: { // listbox
- int y = e->we.click.pt.y - w->widget[3].top;
- if (y >= 0) {
- WP(w, refit_d).sel = (y / (int)w->resize.step_height) + w->vscroll.pos;
- w->SetDirty();
+ switch (v->type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN: command = CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE); break;
+ case VEH_ROAD: command = CMD_REFIT_ROAD_VEH | CMD_MSG(STR_REFIT_ROAD_VEHICLE_CAN_T); break;
+ case VEH_SHIP: command = CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP); break;
+ case VEH_AIRCRAFT: command = CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT); break;
+ }
+ if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8, NULL, command)) delete this;
+ } else {
+ if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8 | this->order << 16, NULL, CMD_ORDER_REFIT)) delete this;
}
- } break;
- case 6: // refit button
- if (WP(w, refit_d).cargo != NULL) {
- const Vehicle *v = GetVehicle(w->window_number);
-
- if (WP(w, refit_d).order == INVALID_VEH_ORDER_ID) {
- int command = 0;
+ }
+ break;
+ }
+ }
- switch (v->type) {
- default: NOT_REACHED();
- case VEH_TRAIN: command = CMD_REFIT_RAIL_VEHICLE | CMD_MSG(STR_RAIL_CAN_T_REFIT_VEHICLE); break;
- case VEH_ROAD: command = CMD_REFIT_ROAD_VEH | CMD_MSG(STR_REFIT_ROAD_VEHICLE_CAN_T); break;
- case VEH_SHIP: command = CMD_REFIT_SHIP | CMD_MSG(STR_9841_CAN_T_REFIT_SHIP); break;
- case VEH_AIRCRAFT: command = CMD_REFIT_AIRCRAFT | CMD_MSG(STR_A042_CAN_T_REFIT_AIRCRAFT); break;
- }
- if (DoCommandP(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8, NULL, command)) delete w;
- } else {
- if (DoCommandP(v->tile, v->index, WP(w, refit_d).cargo->cargo | WP(w, refit_d).cargo->subtype << 8 | WP(w, refit_d).order << 16, NULL, CMD_ORDER_REFIT)) delete w;
- }
- }
- break;
- }
- break;
-
- case WE_RESIZE:
- w->vscroll.cap += e->we.sizing.diff.y / (int)w->resize.step_height;
- w->widget[3].data = (w->vscroll.cap << 8) + 1;
- break;
-
- case WE_DESTROY:
- free(WP(w, refit_d).list->items);
- free(WP(w, refit_d).list);
- break;
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->vscroll.cap += delta.y / (int)this->resize.step_height;
+ this->widget[3].data = (this->vscroll.cap << 8) + 1;
}
-}
+};
static const Widget _vehicle_refit_widgets[] = {
@@ -435,7 +432,6 @@
WC_VEHICLE_REFIT, WC_VEHICLE_VIEW,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_vehicle_refit_widgets,
- VehicleRefitWndProc,
};
/** Show the refit window for a vehicle
@@ -444,46 +440,8 @@
*/
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order)
{
- Window *w;
-
DeleteWindowById(WC_VEHICLE_REFIT, v->index);
-
- w = AllocateWindowDescFront<Window>(&_vehicle_refit_desc, v->index);
- WP(w, refit_d).order = order;
-
- if (w != NULL) {
- w->caption_color = v->owner;
- w->vscroll.cap = 8;
- w->resize.step_height = 14;
- WP(w, refit_d).sel = -1;
- WP(w, refit_d).list = BuildRefitList(v);
- if (v->type == VEH_TRAIN) WP(w, refit_d).length = CountVehiclesInChain(v);
- SetVScrollCount(w, WP(w, refit_d).list->num_lines);
-
- switch (v->type) {
- case VEH_TRAIN:
- w->widget[3].tooltips = STR_RAIL_SELECT_TYPE_OF_CARGO_FOR;
- w->widget[6].data = STR_RAIL_REFIT_VEHICLE;
- w->widget[6].tooltips = STR_RAIL_REFIT_TO_CARRY_HIGHLIGHTED;
- break;
- case VEH_ROAD:
- w->widget[3].tooltips = STR_ROAD_SELECT_TYPE_OF_CARGO_FOR;
- w->widget[6].data = STR_REFIT_ROAD_VEHICLE;
- w->widget[6].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY_HIGHLIGHTED;
- break;
- case VEH_SHIP:
- w->widget[3].tooltips = STR_983D_SELECT_TYPE_OF_CARGO_FOR;
- w->widget[6].data = STR_983C_REFIT_SHIP;
- w->widget[6].tooltips = STR_983E_REFIT_SHIP_TO_CARRY_HIGHLIGHTED;
- break;
- case VEH_AIRCRAFT:
- w->widget[3].tooltips = STR_A03E_SELECT_TYPE_OF_CARGO_FOR;
- w->widget[6].data = STR_A03D_REFIT_AIRCRAFT;
- w->widget[6].tooltips = STR_A03F_REFIT_AIRCRAFT_TO_CARRY;
- break;
- default: NOT_REACHED();
- }
- }
+ new RefitWindow(&_vehicle_refit_desc, v, order);
}
/** Display additional text from NewGRF in the purchase information window */
@@ -841,7 +799,7 @@
*/
struct VehicleListWindow : public Window, public VehicleListBase {
- VehicleListWindow(const WindowDesc *desc, void *data, WindowNumber window_number) : Window(desc, data, window_number)
+ VehicleListWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
{
uint16 window_type = this->window_number & VLW_MASK;
PlayerID player = (PlayerID)GB(this->window_number, 0, 8);
@@ -1028,12 +986,12 @@
VLW_WIDGET_START_ALL,
WIDGET_LIST_END);
- DrawWindowWidgets(this);
+ this->DrawWidgets();
/* draw sorting criteria string */
DrawString(85, 15, _vehicle_sort_listing[this->vehicles.sort_type], TC_BLACK);
/* draw arrow pointing up/down for ascending/descending sorting */
- DrawSortButtonState(this, VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
+ this->DrawSortButtonState(VLW_WIDGET_SORT_ORDER, this->vehicles.flags & VL_DESC ? SBS_DOWN : SBS_UP);
max = min(this->vscroll.pos + this->vscroll.cap, this->vehicles.list_length);
for (i = this->vscroll.pos; i < max; ++i) {
@@ -1187,6 +1145,11 @@
this->vscroll.cap += delta.y / (int)this->resize.step_height;
this->widget[VLW_WIDGET_LIST].data = (this->vscroll.cap << 8) + 1;
}
+
+ virtual void OnInvalidateData(int data)
+ {
+ this->vehicles.flags |= (data == 0 ? VL_REBUILD : VL_RESORT);
+ }
};
static const WindowDesc _player_vehicle_list_train_desc = {
@@ -1194,7 +1157,6 @@
WC_TRAINS_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- NULL
};
static const WindowDesc _player_vehicle_list_road_veh_desc = {
@@ -1202,7 +1164,6 @@
WC_ROADVEH_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- NULL
};
static const WindowDesc _player_vehicle_list_ship_desc = {
@@ -1210,7 +1171,6 @@
WC_SHIPS_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- NULL
};
static const WindowDesc _player_vehicle_list_aircraft_desc = {
@@ -1218,7 +1178,6 @@
WC_AIRCRAFT_LIST, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_list_widgets,
- NULL
};
static void ShowVehicleListWindowLocal(PlayerID player, uint16 VLW_flag, VehicleType vehicle_type, uint16 unique_number)
@@ -1374,78 +1333,6 @@
},
};
-/** Initialize a newly created vehicle details window */
-void CreateVehicleDetailsWindow(Window *w)
-{
- const Vehicle *v = GetVehicle(w->window_number);
-
- switch (v->type) {
- case VEH_TRAIN:
- ResizeWindow(w, 0, 39);
-
- w->vscroll.cap = 6;
- w->height += 12;
- w->resize.step_height = 14;
- w->resize.height = w->height - 14 * 2; // Minimum of 4 wagons in the display
-
- w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_8867_NAME_TRAIN;
- w->widget[VLD_WIDGET_CAPTION].data = STR_8802_DETAILS;
- break;
-
- case VEH_ROAD: {
- w->widget[VLD_WIDGET_CAPTION].data = STR_900C_DETAILS;
- w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_902E_NAME_ROAD_VEHICLE;
-
- if (!RoadVehHasArticPart(v)) break;
-
- /* Draw the text under the vehicle instead of next to it, minus the
- * height already allocated for the cargo of the first vehicle. */
- uint height_extension = 15 - 11;
-
- /* Add space for the cargo amount for each part. */
- for (const Vehicle *u = v; u != NULL; u = u->Next()) {
- height_extension += 11;
- }
-
- ResizeWindow(w, 0, height_extension);
- } break;
-
- case VEH_SHIP:
- w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_982F_NAME_SHIP;
- w->widget[VLD_WIDGET_CAPTION].data = STR_9811_DETAILS;
- break;
-
- case VEH_AIRCRAFT:
- ResizeWindow(w, 0, 11);
- w->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_A032_NAME_AIRCRAFT;
- w->widget[VLD_WIDGET_CAPTION].data = STR_A00C_DETAILS;
- break;
- default: NOT_REACHED();
- }
-
- if (v->type != VEH_TRAIN) {
- w->vscroll.cap = 1;
- w->widget[VLD_WIDGET_MIDDLE_DETAILS].right += 12;
- }
-
- w->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (w->vscroll.cap << 8) + 1;
- w->caption_color = v->owner;
-
- WP(w, vehicledetails_d).tab = 0;
-}
-
-/** Checks whether service interval is enabled for the vehicle. */
-static inline bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type)
-{
- switch (vehicle_type) {
- default: NOT_REACHED();
- case VEH_TRAIN: return _patches.servint_trains != 0; break;
- case VEH_ROAD: return _patches.servint_roadveh != 0; break;
- case VEH_SHIP: return _patches.servint_ships != 0; break;
- case VEH_AIRCRAFT: return _patches.servint_aircraft != 0; break;
- }
- return false; // kill a compiler warning
-}
extern int GetTrainDetailsWndVScroll(VehicleID veh_id, byte det_tab);
extern void DrawTrainDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint16 vscroll_cap, byte det_tab);
@@ -1453,201 +1340,267 @@
extern void DrawShipDetails(const Vehicle *v, int x, int y);
extern void DrawAircraftDetails(const Vehicle *v, int x, int y);
-/**
-* Draw the details for the given vehicle at the position (x, y) of the Details windows
-*
-* @param v current vehicle
-* @param x The x coordinate
-* @param y The y coordinate
-* @param vscroll_pos (train only)
-* @param vscroll_cap (train only)
-* @param det_tab (train only)
-*/
-static inline void DrawVehicleDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint vscroll_cap, byte det_tab)
-{
- switch (v->type) {
- case VEH_TRAIN: DrawTrainDetails(v, x, y, vscroll_pos, vscroll_cap, det_tab); break;
- case VEH_ROAD: DrawRoadVehDetails(v, x, y); break;
- case VEH_SHIP: DrawShipDetails(v, x, y); break;
- case VEH_AIRCRAFT: DrawAircraftDetails(v, x, y); break;
- default: NOT_REACHED();
- }
-}
-
-/** Repaint vehicle details window. */
-static void DrawVehicleDetailsWindow(Window *w)
-{
- const Vehicle *v = GetVehicle(w->window_number);
- byte det_tab = WP(w, vehicledetails_d).tab;
-
- w->SetWidgetDisabledState(VLD_WIDGET_RENAME_VEHICLE, v->owner != _local_player);
-
- if (v->type == VEH_TRAIN) {
- w->DisableWidget(det_tab + VLD_WIDGET_DETAILS_CARGO_CARRIED);
- SetVScrollCount(w, GetTrainDetailsWndVScroll(v->index, det_tab));
- }
+struct VehicleDetailsWindow : Window {
+ int tab;
- w->SetWidgetsHiddenState(v->type != VEH_TRAIN,
- VLD_WIDGET_SCROLLBAR,
- VLD_WIDGET_DETAILS_CARGO_CARRIED,
- VLD_WIDGET_DETAILS_TRAIN_VEHICLES,
- VLD_WIDGET_DETAILS_CAPACITY_OF_EACH,
- VLD_WIDGET_DETAILS_TOTAL_CARGO,
- VLD_WIDGET_RESIZE,
- WIDGET_LIST_END);
-
- /* Disable service-scroller when interval is set to disabled */
- w->SetWidgetsDisabledState(!IsVehicleServiceIntervalEnabled(v->type),
- VLD_WIDGET_INCREASE_SERVICING_INTERVAL,
- VLD_WIDGET_DECREASE_SERVICING_INTERVAL,
- WIDGET_LIST_END);
-
-
- SetDParam(0, v->index);
- DrawWindowWidgets(w);
+ /** Initialize a newly created vehicle details window */
+ VehicleDetailsWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+ {
+ const Vehicle *v = GetVehicle(this->window_number);
- /* Draw running cost */
- SetDParam(1, v->age / 366);
- SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED);
- SetDParam(2, v->max_age / 366);
- SetDParam(3, v->GetDisplayRunningCost());
- DrawString(2, 15, _vehicle_translation_table[VST_VEHICLE_AGE_RUNNING_COST_YR][v->type], TC_FROMSTRING);
+ switch (v->type) {
+ case VEH_TRAIN:
+ ResizeWindow(this, 0, 39);
- /* Draw max speed */
- switch (v->type) {
- case VEH_TRAIN:
- SetDParam(2, v->GetDisplayMaxSpeed());
- SetDParam(1, v->u.rail.cached_power);
- SetDParam(0, v->u.rail.cached_weight);
- SetDParam(3, v->u.rail.cached_max_te / 1000);
- DrawString(2, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
- STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
- STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING);
- break;
+ this->vscroll.cap = 6;
+ this->height += 12;
+ this->resize.step_height = 14;
+ this->resize.height = this->height - 14 * 2; // Minimum of 4 wagons in the display
- case VEH_ROAD:
- case VEH_SHIP:
- case VEH_AIRCRAFT:
- SetDParam(0, v->GetDisplayMaxSpeed());
- DrawString(2, 25, _vehicle_translation_table[VST_VEHICLE_MAX_SPEED][v->type], TC_FROMSTRING);
- break;
+ this->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_8867_NAME_TRAIN;
+ this->widget[VLD_WIDGET_CAPTION].data = STR_8802_DETAILS;
+ break;
- default: NOT_REACHED();
+ case VEH_ROAD: {
+ this->widget[VLD_WIDGET_CAPTION].data = STR_900C_DETAILS;
+ this->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_902E_NAME_ROAD_VEHICLE;
+
+ if (!RoadVehHasArticPart(v)) break;
+
+ /* Draw the text under the vehicle instead of next to it, minus the
+ * height already allocated for the cargo of the first vehicle. */
+ uint height_extension = 15 - 11;
+
+ /* Add space for the cargo amount for each part. */
+ for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+ height_extension += 11;
+ }
+
+ ResizeWindow(this, 0, height_extension);
+ } break;
+
+ case VEH_SHIP:
+ this->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_982F_NAME_SHIP;
+ this->widget[VLD_WIDGET_CAPTION].data = STR_9811_DETAILS;
+ break;
+
+ case VEH_AIRCRAFT:
+ ResizeWindow(this, 0, 11);
+ this->widget[VLD_WIDGET_RENAME_VEHICLE].tooltips = STR_A032_NAME_AIRCRAFT;
+ this->widget[VLD_WIDGET_CAPTION].data = STR_A00C_DETAILS;
+ break;
+ default: NOT_REACHED();
+ }
+
+ if (v->type != VEH_TRAIN) {
+ this->vscroll.cap = 1;
+ this->widget[VLD_WIDGET_MIDDLE_DETAILS].right += 12;
+ }
+
+ this->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (this->vscroll.cap << 8) + 1;
+ this->caption_color = v->owner;
+
+ this->tab = 0;
}
- /* Draw profit */
- SetDParam(0, v->GetDisplayProfitThisYear());
- SetDParam(1, v->GetDisplayProfitLastYear());
- DrawString(2, 35, _vehicle_translation_table[VST_VEHICLE_PROFIT_THIS_YEAR_LAST_YEAR][v->type], TC_FROMSTRING);
-
- /* Draw breakdown & reliability */
- SetDParam(0, v->reliability * 100 >> 16);
- SetDParam(1, v->breakdowns_since_last_service);
- DrawString(2, 45, _vehicle_translation_table[VST_VEHICLE_RELIABILITY_BREAKDOWNS][v->type], TC_FROMSTRING);
-
- /* Draw service interval text */
- SetDParam(0, v->service_interval);
- SetDParam(1, v->date_of_last_service);
- DrawString(13, w->height - (v->type != VEH_TRAIN ? 11 : 23), _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
-
- switch (v->type) {
- case VEH_TRAIN:
- DrawVehicleDetails(v, 2, 57, w->vscroll.pos, w->vscroll.cap, det_tab);
- break;
-
- case VEH_ROAD:
- case VEH_SHIP:
- case VEH_AIRCRAFT:
- DrawVehicleImage(v, 3, 57, INVALID_VEHICLE, 0, 0);
- DrawVehicleDetails(v, 75, 57, w->vscroll.pos, w->vscroll.cap, det_tab);
- break;
-
- default: NOT_REACHED();
+ /** Checks whether service interval is enabled for the vehicle. */
+ static bool IsVehicleServiceIntervalEnabled(const VehicleType vehicle_type)
+ {
+ switch (vehicle_type) {
+ default: NOT_REACHED();
+ case VEH_TRAIN: return _patches.servint_trains != 0; break;
+ case VEH_ROAD: return _patches.servint_roadveh != 0; break;
+ case VEH_SHIP: return _patches.servint_ships != 0; break;
+ case VEH_AIRCRAFT: return _patches.servint_aircraft != 0; break;
+ }
+ return false; // kill a compiler warning
}
-}
-
-/** Message strings for renaming vehicles indexed by vehicle type. */
-static const StringID _name_vehicle_title[] = {
- STR_8865_NAME_TRAIN,
- STR_902C_NAME_ROAD_VEHICLE,
- STR_9831_NAME_SHIP,
- STR_A030_NAME_AIRCRAFT
-};
-
-/** Message strings for error while renaming indexed by vehicle type. */
-static const StringID _name_vehicle_error[] = {
- STR_8866_CAN_T_NAME_TRAIN,
- STR_902D_CAN_T_NAME_ROAD_VEHICLE,
- STR_9832_CAN_T_NAME_SHIP,
- STR_A031_CAN_T_NAME_AIRCRAFT
-};
-
-/** Window event hook for vehicle details. */
-static void VehicleDetailsWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- CreateVehicleDetailsWindow(w);
- break;
- case WE_PAINT:
- DrawVehicleDetailsWindow(w);
- break;
-
- case WE_CLICK: {
- switch (e->we.click.widget) {
- case VLD_WIDGET_RENAME_VEHICLE: {// rename
- const Vehicle *v = GetVehicle(w->window_number);
- SetDParam(0, v->index);
- ShowQueryString(STR_VEHICLE_NAME, _name_vehicle_title[v->type], 31, 150, w, CS_ALPHANUMERAL);
- } break;
-
- case VLD_WIDGET_INCREASE_SERVICING_INTERVAL: // increase int
- case VLD_WIDGET_DECREASE_SERVICING_INTERVAL: { // decrease int
- int mod = _ctrl_pressed ? 5 : 10;
- const Vehicle *v = GetVehicle(w->window_number);
-
- mod = (e->we.click.widget == VLD_WIDGET_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
- mod = GetServiceIntervalClamped(mod + v->service_interval);
- if (mod == v->service_interval) return;
-
- DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
- } break;
+ /**
+ * Draw the details for the given vehicle at the position (x, y) of the Details windows
+ *
+ * @param v current vehicle
+ * @param x The x coordinate
+ * @param y The y coordinate
+ * @param vscroll_pos (train only)
+ * @param vscroll_cap (train only)
+ * @param det_tab (train only)
+ */
+ static void DrawVehicleDetails(const Vehicle *v, int x, int y, int vscroll_pos, uint vscroll_cap, byte det_tab)
+ {
+ switch (v->type) {
+ case VEH_TRAIN: DrawTrainDetails(v, x, y, vscroll_pos, vscroll_cap, det_tab); break;
+ case VEH_ROAD: DrawRoadVehDetails(v, x, y); break;
+ case VEH_SHIP: DrawShipDetails(v, x, y); break;
+ case VEH_AIRCRAFT: DrawAircraftDetails(v, x, y); break;
+ default: NOT_REACHED();
+ }
+ }
- case VLD_WIDGET_DETAILS_CARGO_CARRIED:
- case VLD_WIDGET_DETAILS_TRAIN_VEHICLES:
- case VLD_WIDGET_DETAILS_CAPACITY_OF_EACH:
- case VLD_WIDGET_DETAILS_TOTAL_CARGO:
- w->SetWidgetsDisabledState(false,
- VLD_WIDGET_DETAILS_CARGO_CARRIED,
- VLD_WIDGET_DETAILS_TRAIN_VEHICLES,
- VLD_WIDGET_DETAILS_CAPACITY_OF_EACH,
- VLD_WIDGET_DETAILS_TOTAL_CARGO,
- e->we.click.widget,
- WIDGET_LIST_END);
+ /** Repaint vehicle details window. */
+ virtual void OnPaint()
+ {
+ const Vehicle *v = GetVehicle(this->window_number);
+ byte det_tab = this->tab;
- WP(w, vehicledetails_d).tab = e->we.click.widget - VLD_WIDGET_DETAILS_CARGO_CARRIED;
- w->SetDirty();
- break;
- }
- } break;
+ this->SetWidgetDisabledState(VLD_WIDGET_RENAME_VEHICLE, v->owner != _local_player);
- case WE_ON_EDIT_TEXT:
- if (!StrEmpty(e->we.edittext.str)) {
- _cmd_text = e->we.edittext.str;
- DoCommandP(0, w->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(_name_vehicle_error[GetVehicle(w->window_number)->type]));
- }
- break;
+ if (v->type == VEH_TRAIN) {
+ this->DisableWidget(det_tab + VLD_WIDGET_DETAILS_CARGO_CARRIED);
+ SetVScrollCount(this, GetTrainDetailsWndVScroll(v->index, det_tab));
+ }
- case WE_RESIZE:
- if (e->we.sizing.diff.x != 0) ResizeButtons(w, VLD_WIDGET_DETAILS_CARGO_CARRIED, VLD_WIDGET_DETAILS_TOTAL_CARGO);
- if (e->we.sizing.diff.y == 0) break;
+ this->SetWidgetsHiddenState(v->type != VEH_TRAIN,
+ VLD_WIDGET_SCROLLBAR,
+ VLD_WIDGET_DETAILS_CARGO_CARRIED,
+ VLD_WIDGET_DETAILS_TRAIN_VEHICLES,
+ VLD_WIDGET_DETAILS_CAPACITY_OF_EACH,
+ VLD_WIDGET_DETAILS_TOTAL_CARGO,
+ VLD_WIDGET_RESIZE,
+ WIDGET_LIST_END);
- w->vscroll.cap += e->we.sizing.diff.y / 14;
- w->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (w->vscroll.cap << 8) + 1;
- break;
+ /* Disable service-scroller when interval is set to disabled */
+ this->SetWidgetsDisabledState(!IsVehicleServiceIntervalEnabled(v->type),
+ VLD_WIDGET_INCREASE_SERVICING_INTERVAL,
+ VLD_WIDGET_DECREASE_SERVICING_INTERVAL,
+ WIDGET_LIST_END);
+
+
+ SetDParam(0, v->index);
+ this->DrawWidgets();
+
+ /* Draw running cost */
+ SetDParam(1, v->age / 366);
+ SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED);
+ SetDParam(2, v->max_age / 366);
+ SetDParam(3, v->GetDisplayRunningCost());
+ DrawString(2, 15, _vehicle_translation_table[VST_VEHICLE_AGE_RUNNING_COST_YR][v->type], TC_FROMSTRING);
+
+ /* Draw max speed */
+ switch (v->type) {
+ case VEH_TRAIN:
+ SetDParam(2, v->GetDisplayMaxSpeed());
+ SetDParam(1, v->u.rail.cached_power);
+ SetDParam(0, v->u.rail.cached_weight);
+ SetDParam(3, v->u.rail.cached_max_te / 1000);
+ DrawString(2, 25, (_patches.realistic_acceleration && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
+ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
+ STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, TC_FROMSTRING);
+ break;
+
+ case VEH_ROAD:
+ case VEH_SHIP:
+ case VEH_AIRCRAFT:
+ SetDParam(0, v->GetDisplayMaxSpeed());
+ DrawString(2, 25, _vehicle_translation_table[VST_VEHICLE_MAX_SPEED][v->type], TC_FROMSTRING);
+ break;
+
+ default: NOT_REACHED();
+ }
+
+ /* Draw profit */
+ SetDParam(0, v->GetDisplayProfitThisYear());
+ SetDParam(1, v->GetDisplayProfitLastYear());
+ DrawString(2, 35, _vehicle_translation_table[VST_VEHICLE_PROFIT_THIS_YEAR_LAST_YEAR][v->type], TC_FROMSTRING);
+
+ /* Draw breakdown & reliability */
+ SetDParam(0, v->reliability * 100 >> 16);
+ SetDParam(1, v->breakdowns_since_last_service);
+ DrawString(2, 45, _vehicle_translation_table[VST_VEHICLE_RELIABILITY_BREAKDOWNS][v->type], TC_FROMSTRING);
+
+ /* Draw service interval text */
+ SetDParam(0, v->service_interval);
+ SetDParam(1, v->date_of_last_service);
+ DrawString(13, this->height - (v->type != VEH_TRAIN ? 11 : 23), _patches.servint_ispercent ? STR_SERVICING_INTERVAL_PERCENT : STR_883C_SERVICING_INTERVAL_DAYS, TC_FROMSTRING);
+
+ switch (v->type) {
+ case VEH_TRAIN:
+ DrawVehicleDetails(v, 2, 57, this->vscroll.pos, this->vscroll.cap, det_tab);
+ break;
+
+ case VEH_ROAD:
+ case VEH_SHIP:
+ case VEH_AIRCRAFT:
+ DrawVehicleImage(v, 3, 57, INVALID_VEHICLE, 0, 0);
+ DrawVehicleDetails(v, 75, 57, this->vscroll.pos, this->vscroll.cap, det_tab);
+ break;
+
+ default: NOT_REACHED();
+ }
}
-}
+
+ virtual void OnClick(Point pt, int widget)
+ {
+ /** Message strings for renaming vehicles indexed by vehicle type. */
+ static const StringID _name_vehicle_title[] = {
+ STR_8865_NAME_TRAIN,
+ STR_902C_NAME_ROAD_VEHICLE,
+ STR_9831_NAME_SHIP,
+ STR_A030_NAME_AIRCRAFT
+ };
+
+ switch (widget) {
+ case VLD_WIDGET_RENAME_VEHICLE: {// rename
+ const Vehicle *v = GetVehicle(this->window_number);
+ SetDParam(0, v->index);
+ ShowQueryString(STR_VEHICLE_NAME, _name_vehicle_title[v->type], 31, 150, this, CS_ALPHANUMERAL);
+ } break;
+
+ case VLD_WIDGET_INCREASE_SERVICING_INTERVAL: // increase int
+ case VLD_WIDGET_DECREASE_SERVICING_INTERVAL: { // decrease int
+ int mod = _ctrl_pressed ? 5 : 10;
+ const Vehicle *v = GetVehicle(this->window_number);
+
+ mod = (widget == VLD_WIDGET_DECREASE_SERVICING_INTERVAL) ? -mod : mod;
+ mod = GetServiceIntervalClamped(mod + v->service_interval);
+ if (mod == v->service_interval) return;
+
+ DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
+ } break;
+
+ case VLD_WIDGET_DETAILS_CARGO_CARRIED:
+ case VLD_WIDGET_DETAILS_TRAIN_VEHICLES:
+ case VLD_WIDGET_DETAILS_CAPACITY_OF_EACH:
+ case VLD_WIDGET_DETAILS_TOTAL_CARGO:
+ this->SetWidgetsDisabledState(false,
+ VLD_WIDGET_DETAILS_CARGO_CARRIED,
+ VLD_WIDGET_DETAILS_TRAIN_VEHICLES,
+ VLD_WIDGET_DETAILS_CAPACITY_OF_EACH,
+ VLD_WIDGET_DETAILS_TOTAL_CARGO,
+ widget,
+ WIDGET_LIST_END);
+
+ this->tab = widget - VLD_WIDGET_DETAILS_CARGO_CARRIED;
+ this->SetDirty();
+ break;
+ }
+ }
+
+ virtual void OnQueryTextFinished(char *str)
+ {
+ /** Message strings for error while renaming indexed by vehicle type. */
+ static const StringID _name_vehicle_error[] = {
+ STR_8866_CAN_T_NAME_TRAIN,
+ STR_902D_CAN_T_NAME_ROAD_VEHICLE,
+ STR_9832_CAN_T_NAME_SHIP,
+ STR_A031_CAN_T_NAME_AIRCRAFT
+ };
+
+ if (!StrEmpty(str)) {
+ _cmd_text = str;
+ DoCommandP(0, this->window_number, 0, NULL, CMD_NAME_VEHICLE | CMD_MSG(_name_vehicle_error[GetVehicle(this->window_number)->type]));
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ if (delta.x != 0) ResizeButtons(this, VLD_WIDGET_DETAILS_CARGO_CARRIED, VLD_WIDGET_DETAILS_TOTAL_CARGO);
+ if (delta.y == 0) return;
+
+ this->vscroll.cap += delta.y / 14;
+ this->widget[VLD_WIDGET_MIDDLE_DETAILS].data = (this->vscroll.cap << 8) + 1;
+ }
+};
/** Vehicle details window descriptor. */
static const WindowDesc _vehicle_details_desc = {
@@ -1655,7 +1608,6 @@
WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
_vehicle_details_widgets,
- VehicleDetailsWndProc
};
/** Shows the vehicle details window of the given vehicle. */
@@ -1663,7 +1615,7 @@
{
DeleteWindowById(WC_VEHICLE_ORDERS, v->index);
DeleteWindowById(WC_VEHICLE_DETAILS, v->index);
- AllocateWindowDescFront<Window>(&_vehicle_details_desc, v->index);
+ AllocateWindowDescFront<VehicleDetailsWindow>(&_vehicle_details_desc, v->index);
}
@@ -1691,15 +1643,12 @@
};
-static void VehicleViewWndProc(Window *w, WindowEvent *e);
-
/** Vehicle view window descriptor for all vehicles but trains. */
static const WindowDesc _vehicle_view_desc = {
WDP_AUTO, WDP_AUTO, 250, 116, 250, 116,
WC_VEHICLE_VIEW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_view_widgets,
- VehicleViewWndProc
};
/** Vehicle view window descriptor for trains. Only minimum_height and
@@ -1710,7 +1659,6 @@
WC_VEHICLE_VIEW, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_vehicle_view_widgets,
- VehicleViewWndProc
};
@@ -1736,300 +1684,6 @@
static const int VV_INITIAL_VIEWPORT_HEIGHT = 84;
static const int VV_INITIAL_VIEWPORT_HEIGHT_TRAIN = 102;
-/** Shows the vehicle view window of the given vehicle. */
-void ShowVehicleViewWindow(const Vehicle *v)
-{
- Window *w = AllocateWindowDescFront<Window>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
-
- if (w != NULL) {
- w->caption_color = v->owner;
- InitializeWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
- (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT,
- w->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
- }
-}
-
-/** Initialize a newly created vehicle view window */
-static void CreateVehicleViewWindow(Window *w)
-{
- const Vehicle *v = GetVehicle(w->window_number);
-
- /*
- * fill in data and tooltip codes for the widgets and
- * move some of the buttons for trains
- */
- switch (v->type) {
- case VEH_TRAIN:
- w->widget[VVW_WIDGET_CAPTION].data = STR_882E;
-
- w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK;
-
- w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN;
-
- w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT;
- w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT;
-
- w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY;
-
- w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS;
-
- w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS;
-
- w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN;
- w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO;
-
- w->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN;
-
-
- /* due to more buttons we must modify the layout a bit for trains */
- w->widget[VVW_WIDGET_PANEL].bottom = 121;
- w->widget[VVW_WIDGET_VIEWPORT].bottom = 119;
-
- w->widget[VVW_WIDGET_START_STOP_VEH].top = 122;
- w->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133;
-
- w->widget[VVW_WIDGET_REFIT_VEH].top = 68;
- w->widget[VVW_WIDGET_REFIT_VEH].bottom = 85;
-
- w->widget[VVW_WIDGET_SHOW_ORDERS].top = 86;
- w->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103;
-
- w->widget[VVW_WIDGET_SHOW_DETAILS].top = 104;
- w->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121;
-
- w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122;
- w->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121;
-
- w->widget[VVW_WIDGET_RESIZE].top = 122;
- w->widget[VVW_WIDGET_RESIZE].bottom = 133;
-
- w->widget[VVW_WIDGET_TURN_AROUND].top = 68;
- w->widget[VVW_WIDGET_TURN_AROUND].bottom = 85;
- break;
-
- case VEH_ROAD:
- w->widget[VVW_WIDGET_CAPTION].data = STR_9002;
-
- w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION;
-
- w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE;
-
- w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT;
- w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT;
-
- w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY;
-
- w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS;
-
- w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS;
-
- w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH;
- w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO;
-
- w->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true);
- break;
-
- case VEH_SHIP:
- w->widget[VVW_WIDGET_CAPTION].data = STR_980F;
-
- w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK;
-
- w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP;
-
- w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT;
- w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT;
-
- w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY;
-
- w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS;
-
- w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS;
-
- w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP;
- w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO;
-
- w->SetWidgetsHiddenState(true,
- VVW_WIDGET_TURN_AROUND,
- VVW_WIDGET_FORCE_PROCEED,
- WIDGET_LIST_END);
- break;
-
- case VEH_AIRCRAFT:
- w->widget[VVW_WIDGET_CAPTION].data = STR_A00A;
-
- w->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION;
-
- w->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT;
-
- w->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT;
- w->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR;
-
- w->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY;
-
- w->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS;
-
- w->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS;
-
- w->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT;
- w->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO;
-
- w->SetWidgetsHiddenState(true,
- VVW_WIDGET_TURN_AROUND,
- VVW_WIDGET_FORCE_PROCEED,
- WIDGET_LIST_END);
- break;
-
- default: NOT_REACHED();
- }
-}
-
-/** Checks whether the vehicle may be refitted at the moment.*/
-static bool IsVehicleRefitable(const Vehicle *v)
-{
- /* Why is this so different for different vehicles?
- * Does maybe work one solution for all?
- */
- switch (v->type) {
- case VEH_TRAIN: return false;
- case VEH_ROAD: return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot();
- case VEH_SHIP: return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot();
- case VEH_AIRCRAFT: return v->IsStoppedInDepot();
- default: NOT_REACHED();
- }
-}
-
-/** Message strings for heading to depot indexed by vehicle type. */
-static const StringID _heading_for_depot_strings[] = {
- STR_HEADING_FOR_TRAIN_DEPOT,
- STR_HEADING_FOR_ROAD_DEPOT,
- STR_HEADING_FOR_SHIP_DEPOT,
- STR_HEADING_FOR_HANGAR,
-};
-
-/** Message strings for heading to depot and servicing indexed by vehicle type. */
-static const StringID _heading_for_depot_service_strings[] = {
- STR_HEADING_FOR_TRAIN_DEPOT_SERVICE,
- STR_HEADING_FOR_ROAD_DEPOT_SERVICE,
- STR_HEADING_FOR_SHIP_DEPOT_SERVICE,
- STR_HEADING_FOR_HANGAR_SERVICE,
-};
-
-/** Repaint vehicle view window. */
-static void DrawVehicleViewWindow(Window *w)
-{
- const Vehicle *v = GetVehicle(w->window_number);
- StringID str;
- bool is_localplayer = v->owner == _local_player;
- bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
-
- w->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer);
- w->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH,
- !refitable_and_stopped_in_depot || !is_localplayer);
- w->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer);
-
- if (v->type == VEH_TRAIN) {
- w->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer);
- w->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer);
-
- /* Cargo refit button is disabled, until we know we can enable it below. */
-
- if (is_localplayer) {
- /* See if any vehicle can be refitted */
- for (const Vehicle *u = v; u != NULL; u = u->Next()) {
- if (EngInfo(u->engine_type)->refit_mask != 0 ||
- (RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) {
- w->EnableWidget(VVW_WIDGET_REFIT_VEH);
- /* We have a refittable carriage, bail out */
- break;
- }
- }
- }
- }
-
- /* draw widgets & caption */
- SetDParam(0, v->index);
- DrawWindowWidgets(w);
-
- if (v->vehstatus & VS_CRASHED) {
- str = STR_8863_CRASHED;
- } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
- str = STR_885C_BROKEN_DOWN;
- } else if (v->vehstatus & VS_STOPPED) {
- if (v->type == VEH_TRAIN) {
- if (v->cur_speed == 0) {
- if (v->u.rail.cached_power == 0) {
- str = STR_TRAIN_NO_POWER;
- } else {
- str = STR_8861_STOPPED;
- }
- } else {
- SetDParam(0, v->GetDisplaySpeed());
- str = STR_TRAIN_STOPPING + _patches.vehicle_speed;
- }
- } else { // no train
- str = STR_8861_STOPPED;
- }
- } else { // vehicle is in a "normal" state, show current order
- switch (v->current_order.GetType()) {
- case OT_GOTO_STATION: {
- SetDParam(0, v->current_order.GetDestination());
- SetDParam(1, v->GetDisplaySpeed());
- str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
- } break;
-
- case OT_GOTO_DEPOT: {
- if (v->type == VEH_AIRCRAFT) {
- /* Aircrafts always go to a station, even if you say depot */
- SetDParam(0, v->current_order.GetDestination());
- SetDParam(1, v->GetDisplaySpeed());
- } else {
- Depot *depot = GetDepot(v->current_order.GetDestination());
- SetDParam(0, depot->town_index);
- SetDParam(1, v->GetDisplaySpeed());
- }
- if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
- str = _heading_for_depot_strings[v->type] + _patches.vehicle_speed;
- } else {
- str = _heading_for_depot_service_strings[v->type] + _patches.vehicle_speed;
- }
- } break;
-
- case OT_LOADING:
- str = STR_882F_LOADING_UNLOADING;
- break;
-
- case OT_GOTO_WAYPOINT: {
- assert(v->type == VEH_TRAIN);
- SetDParam(0, v->current_order.GetDestination());
- str = STR_HEADING_FOR_WAYPOINT + _patches.vehicle_speed;
- SetDParam(1, v->GetDisplaySpeed());
- break;
- }
-
- case OT_LEAVESTATION:
- if (v->type != VEH_AIRCRAFT) {
- str = STR_LEAVING;
- break;
- }
- /* fall-through if aircraft. Does this even happen? */
-
- default:
- if (v->num_orders == 0) {
- str = STR_NO_ORDERS + _patches.vehicle_speed;
- SetDParam(0, v->GetDisplaySpeed());
- } else {
- str = STR_EMPTY;
- }
- break;
- }
- }
-
- /* draw the flag plus orders */
- DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1);
- DrawStringCenteredTruncated(w->widget[VVW_WIDGET_START_STOP_VEH].left + 8, w->widget[VVW_WIDGET_START_STOP_VEH].right, w->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING);
- DrawWindowViewport(w);
-}
-
/** Command indices for the _vehicle_command_translation_table. */
enum VehicleCommandTranslation {
VCT_CMD_START_STOP = 0,
@@ -2067,104 +1721,387 @@
},
};
-/** Window event hook for vehicle view. */
-static void VehicleViewWndProc(Window *w, WindowEvent *e)
+/** Checks whether the vehicle may be refitted at the moment.*/
+static bool IsVehicleRefitable(const Vehicle *v)
{
- switch (e->event) {
- case WE_CREATE:
- CreateVehicleViewWindow(w);
- break;
-
- case WE_PAINT:
- DrawVehicleViewWindow(w);
- break;
+ /* Why is this so different for different vehicles?
+ * Does maybe work one solution for all?
+ */
+ switch (v->type) {
+ case VEH_TRAIN: return false;
+ case VEH_ROAD: return EngInfo(v->engine_type)->refit_mask != 0 && v->IsStoppedInDepot();
+ case VEH_SHIP: return ShipVehInfo(v->engine_type)->refittable && v->IsStoppedInDepot();
+ case VEH_AIRCRAFT: return v->IsStoppedInDepot();
+ default: NOT_REACHED();
+ }
+}
- case WE_CLICK: {
- const Vehicle *v = GetVehicle(w->window_number);
+struct VehicleViewWindow : Window {
+ VehicleViewWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
+ {
+ const Vehicle *v = GetVehicle(this->window_number);
- switch (e->we.click.widget) {
- case VVW_WIDGET_START_STOP_VEH: /* start stop */
- DoCommandP(v->tile, v->index, 0, NULL,
- _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]);
- break;
- case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */
- const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
- /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
- if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) {
- mainwindow->viewport->follow_vehicle = v->index;
+ this->caption_color = v->owner;
+ InitializeWindowViewport(this, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH,
+ (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT,
+ this->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]);
+
+ /*
+ * fill in data and tooltip codes for the widgets and
+ * move some of the buttons for trains
+ */
+ switch (v->type) {
+ case VEH_TRAIN:
+ this->widget[VVW_WIDGET_CAPTION].data = STR_882E;
+
+ this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_8846_CURRENT_TRAIN_ACTION_CLICK;
+
+ this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_8848_CENTER_MAIN_VIEW_ON_TRAIN;
+
+ this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_TRAIN_TODEPOT;
+ this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_8849_SEND_TRAIN_TO_DEPOT;
+
+ this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_RAIL_REFIT_VEHICLE_TO_CARRY;
+
+ this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_8847_SHOW_TRAIN_S_ORDERS;
+
+ this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_884C_SHOW_TRAIN_DETAILS;
+
+ this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_TRAIN;
+ this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_TRAIN_INFO;
+
+ this->widget[VVW_WIDGET_TURN_AROUND].tooltips = STR_884B_REVERSE_DIRECTION_OF_TRAIN;
+
+
+ /* due to more buttons we must modify the layout a bit for trains */
+ this->widget[VVW_WIDGET_PANEL].bottom = 121;
+ this->widget[VVW_WIDGET_VIEWPORT].bottom = 119;
+
+ this->widget[VVW_WIDGET_START_STOP_VEH].top = 122;
+ this->widget[VVW_WIDGET_START_STOP_VEH].bottom = 133;
+
+ this->widget[VVW_WIDGET_REFIT_VEH].top = 68;
+ this->widget[VVW_WIDGET_REFIT_VEH].bottom = 85;
+
+ this->widget[VVW_WIDGET_SHOW_ORDERS].top = 86;
+ this->widget[VVW_WIDGET_SHOW_ORDERS].bottom = 103;
+
+ this->widget[VVW_WIDGET_SHOW_DETAILS].top = 104;
+ this->widget[VVW_WIDGET_SHOW_DETAILS].bottom = 121;
+
+ this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].top = 122;
+ this->widget[VVW_WIDGET_EMPTY_BOTTOM_RIGHT].bottom = 121;
+
+ this->widget[VVW_WIDGET_RESIZE].top = 122;
+ this->widget[VVW_WIDGET_RESIZE].bottom = 133;
+
+ this->widget[VVW_WIDGET_TURN_AROUND].top = 68;
+ this->widget[VVW_WIDGET_TURN_AROUND].bottom = 85;
+ break;
+
+ case VEH_ROAD:
+ this->widget[VVW_WIDGET_CAPTION].data = STR_9002;
+
+ this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_901C_CURRENT_VEHICLE_ACTION;
+
+ this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_901E_CENTER_MAIN_VIEW_ON_VEHICLE;
+
+ this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_ROADVEH_TODEPOT;
+ this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_901F_SEND_VEHICLE_TO_DEPOT;
+
+ this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_REFIT_ROAD_VEHICLE_TO_CARRY;
+
+ this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_901D_SHOW_VEHICLE_S_ORDERS;
+
+ this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_9021_SHOW_ROAD_VEHICLE_DETAILS;
+
+ this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_ROADVEH;
+ this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_ROAD_VEHICLE_INFO;
+
+ this->SetWidgetHiddenState(VVW_WIDGET_FORCE_PROCEED, true);
+ break;
+
+ case VEH_SHIP:
+ this->widget[VVW_WIDGET_CAPTION].data = STR_980F;
+
+ this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_9827_CURRENT_SHIP_ACTION_CLICK;
+
+ this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_9829_CENTER_MAIN_VIEW_ON_SHIP;
+
+ this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_SHIP_TODEPOT;
+ this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_982A_SEND_SHIP_TO_DEPOT;
+
+ this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_983A_REFIT_CARGO_SHIP_TO_CARRY;
+
+ this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_9828_SHOW_SHIP_S_ORDERS;
+
+ this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_982B_SHOW_SHIP_DETAILS;
+
+ this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_SHIP;
+ this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_SHIP_INFO;
+
+ this->SetWidgetsHiddenState(true,
+ VVW_WIDGET_TURN_AROUND,
+ VVW_WIDGET_FORCE_PROCEED,
+ WIDGET_LIST_END);
+ break;
+
+ case VEH_AIRCRAFT:
+ this->widget[VVW_WIDGET_CAPTION].data = STR_A00A;
+
+ this->widget[VVW_WIDGET_START_STOP_VEH].tooltips = STR_A027_CURRENT_AIRCRAFT_ACTION;
+
+ this->widget[VVW_WIDGET_CENTER_MAIN_VIEH].tooltips = STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT;
+
+ this->widget[VVW_WIDGET_GOTO_DEPOT].data = SPR_SEND_AIRCRAFT_TODEPOT;
+ this->widget[VVW_WIDGET_GOTO_DEPOT].tooltips = STR_A02A_SEND_AIRCRAFT_TO_HANGAR;
+
+ this->widget[VVW_WIDGET_REFIT_VEH].tooltips = STR_A03B_REFIT_AIRCRAFT_TO_CARRY;
+
+ this->widget[VVW_WIDGET_SHOW_ORDERS].tooltips = STR_A028_SHOW_AIRCRAFT_S_ORDERS;
+
+ this->widget[VVW_WIDGET_SHOW_DETAILS].tooltips = STR_A02B_SHOW_AIRCRAFT_DETAILS;
+
+ this->widget[VVW_WIDGET_CLONE_VEH].data = SPR_CLONE_AIRCRAFT;
+ this->widget[VVW_WIDGET_CLONE_VEH].tooltips = STR_CLONE_AIRCRAFT_INFO;
+
+ this->SetWidgetsHiddenState(true,
+ VVW_WIDGET_TURN_AROUND,
+ VVW_WIDGET_FORCE_PROCEED,
+ WIDGET_LIST_END);
+ break;
+
+ default: NOT_REACHED();
+ }
+ }
+
+ ~VehicleViewWindow()
+ {
+ DeleteWindowById(WC_VEHICLE_ORDERS, this->window_number);
+ DeleteWindowById(WC_VEHICLE_REFIT, this->window_number);
+ DeleteWindowById(WC_VEHICLE_DETAILS, this->window_number);
+ DeleteWindowById(WC_VEHICLE_TIMETABLE, this->window_number);
+ }
+
+ virtual void OnPaint()
+ {
+ /** Message strings for heading to depot indexed by vehicle type. */
+ static const StringID _heading_for_depot_strings[] = {
+ STR_HEADING_FOR_TRAIN_DEPOT,
+ STR_HEADING_FOR_ROAD_DEPOT,
+ STR_HEADING_FOR_SHIP_DEPOT,
+ STR_HEADING_FOR_HANGAR,
+ };
+
+ /** Message strings for heading to depot and servicing indexed by vehicle type. */
+ static const StringID _heading_for_depot_service_strings[] = {
+ STR_HEADING_FOR_TRAIN_DEPOT_SERVICE,
+ STR_HEADING_FOR_ROAD_DEPOT_SERVICE,
+ STR_HEADING_FOR_SHIP_DEPOT_SERVICE,
+ STR_HEADING_FOR_HANGAR_SERVICE,
+ };
+
+ const Vehicle *v = GetVehicle(this->window_number);
+ StringID str;
+ bool is_localplayer = v->owner == _local_player;
+ bool refitable_and_stopped_in_depot = IsVehicleRefitable(v);
+
+ this->SetWidgetDisabledState(VVW_WIDGET_GOTO_DEPOT, !is_localplayer);
+ this->SetWidgetDisabledState(VVW_WIDGET_REFIT_VEH,
+ !refitable_and_stopped_in_depot || !is_localplayer);
+ this->SetWidgetDisabledState(VVW_WIDGET_CLONE_VEH, !is_localplayer);
+
+ if (v->type == VEH_TRAIN) {
+ this->SetWidgetDisabledState(VVW_WIDGET_FORCE_PROCEED, !is_localplayer);
+ this->SetWidgetDisabledState(VVW_WIDGET_TURN_AROUND, !is_localplayer);
+
+ /* Cargo refit button is disabled, until we know we can enable it below. */
+
+ if (is_localplayer) {
+ /* See if any vehicle can be refitted */
+ for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+ if (EngInfo(u->engine_type)->refit_mask != 0 ||
+ (RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON && v->cargo_cap != 0)) {
+ this->EnableWidget(VVW_WIDGET_REFIT_VEH);
+ /* We have a refittable carriage, bail out */
+ break;
+ }
+ }
+ }
+ }
+
+ /* draw widgets & caption */
+ SetDParam(0, v->index);
+ this->DrawWidgets();
+
+ if (v->vehstatus & VS_CRASHED) {
+ str = STR_8863_CRASHED;
+ } else if (v->type != VEH_AIRCRAFT && v->breakdown_ctr == 1) { // check for aircraft necessary?
+ str = STR_885C_BROKEN_DOWN;
+ } else if (v->vehstatus & VS_STOPPED) {
+ if (v->type == VEH_TRAIN) {
+ if (v->cur_speed == 0) {
+ if (v->u.rail.cached_power == 0) {
+ str = STR_TRAIN_NO_POWER;
} else {
- ScrollMainWindowTo(v->x_pos, v->y_pos);
+ str = STR_8861_STOPPED;
+ }
+ } else {
+ SetDParam(0, v->GetDisplaySpeed());
+ str = STR_TRAIN_STOPPING + _patches.vehicle_speed;
+ }
+ } else { // no train
+ str = STR_8861_STOPPED;
+ }
+ } else { // vehicle is in a "normal" state, show current order
+ switch (v->current_order.GetType()) {
+ case OT_GOTO_STATION: {
+ SetDParam(0, v->current_order.GetDestination());
+ SetDParam(1, v->GetDisplaySpeed());
+ str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
+ } break;
+
+ case OT_GOTO_DEPOT: {
+ if (v->type == VEH_AIRCRAFT) {
+ /* Aircrafts always go to a station, even if you say depot */
+ SetDParam(0, v->current_order.GetDestination());
+ SetDParam(1, v->GetDisplaySpeed());
+ } else {
+ Depot *depot = GetDepot(v->current_order.GetDestination());
+ SetDParam(0, depot->town_index);
+ SetDParam(1, v->GetDisplaySpeed());
+ }
+ if ((v->current_order.GetDepotActionType() & ODATFB_HALT) && !(v->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
+ str = _heading_for_depot_strings[v->type] + _patches.vehicle_speed;
+ } else {
+ str = _heading_for_depot_service_strings[v->type] + _patches.vehicle_speed;
}
} break;
- case VVW_WIDGET_GOTO_DEPOT: /* goto hangar */
- DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL,
- _vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]);
- break;
- case VVW_WIDGET_REFIT_VEH: /* refit */
- ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
- break;
- case VVW_WIDGET_SHOW_ORDERS: /* show orders */
- if (_ctrl_pressed) {
- ShowTimetableWindow(v);
- } else {
- ShowOrdersWindow(v);
- }
+ case OT_LOADING:
+ str = STR_882F_LOADING_UNLOADING;
break;
- case VVW_WIDGET_SHOW_DETAILS: /* show details */
- ShowVehicleDetailsWindow(v);
- break;
- case VVW_WIDGET_CLONE_VEH: /* clone vehicle */
- DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle,
- _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]);
+
+ case OT_GOTO_WAYPOINT: {
+ assert(v->type == VEH_TRAIN);
+ SetDParam(0, v->current_order.GetDestination());
+ str = STR_HEADING_FOR_WAYPOINT + _patches.vehicle_speed;
+ SetDParam(1, v->GetDisplaySpeed());
break;
- case VVW_WIDGET_TURN_AROUND: /* turn around */
- assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
- DoCommandP(v->tile, v->index, 0, NULL,
- _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
- break;
- case VVW_WIDGET_FORCE_PROCEED: /* force proceed */
- assert(v->type == VEH_TRAIN);
- DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
+ }
+
+ case OT_LEAVESTATION:
+ if (v->type != VEH_AIRCRAFT) {
+ str = STR_LEAVING;
+ break;
+ }
+ /* fall-through if aircraft. Does this even happen? */
+
+ default:
+ if (v->num_orders == 0) {
+ str = STR_NO_ORDERS + _patches.vehicle_speed;
+ SetDParam(0, v->GetDisplaySpeed());
+ } else {
+ str = STR_EMPTY;
+ }
break;
}
- } break;
-
- case WE_RESIZE:
- w->viewport->width += e->we.sizing.diff.x;
- w->viewport->height += e->we.sizing.diff.y;
- w->viewport->virtual_width += e->we.sizing.diff.x;
- w->viewport->virtual_height += e->we.sizing.diff.y;
- break;
-
- case WE_DESTROY:
- DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
- DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
- DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number);
- DeleteWindowById(WC_VEHICLE_TIMETABLE, w->window_number);
- break;
+ }
- case WE_TICK: {
- const Vehicle *v = GetVehicle(w->window_number);
- bool veh_stopped = v->IsStoppedInDepot();
+ /* draw the flag plus orders */
+ DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, PAL_NONE, 2, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1);
+ DrawStringCenteredTruncated(this->widget[VVW_WIDGET_START_STOP_VEH].left + 8, this->widget[VVW_WIDGET_START_STOP_VEH].right, this->widget[VVW_WIDGET_START_STOP_VEH].top + 1, str, TC_FROMSTRING);
+ this->DrawViewport();
+ }
- /* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already
- * stopped in depot.
- * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is
- * allowed only while in depot and stopped.
- * This sytem allows to have two buttons, on top of each other.
- * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
- if (veh_stopped != w->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == w->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) {
- w->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped); // send to depot
- w->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone
- if (v->type == VEH_ROAD || v->type == VEH_TRAIN) {
- w->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit
- w->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped); // force turn around
+ virtual void OnClick(Point pt, int widget)
+ {
+ const Vehicle *v = GetVehicle(this->window_number);
+
+ switch (widget) {
+ case VVW_WIDGET_START_STOP_VEH: // start stop
+ DoCommandP(v->tile, v->index, 0, NULL,
+ _vehicle_command_translation_table[VCT_CMD_START_STOP][v->type]);
+ break;
+ case VVW_WIDGET_CENTER_MAIN_VIEH: {/* center main view */
+ const Window *mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
+ /* code to allow the main window to 'follow' the vehicle if the ctrl key is pressed */
+ if (_ctrl_pressed && mainwindow->viewport->zoom == ZOOM_LVL_NORMAL) {
+ mainwindow->viewport->follow_vehicle = v->index;
+ } else {
+ ScrollMainWindowTo(v->x_pos, v->y_pos);
}
- w->SetDirty();
+ } break;
+
+ case VVW_WIDGET_GOTO_DEPOT: // goto hangar
+ DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL,
+ _vehicle_command_translation_table[VCT_CMD_GOTO_DEPOT][v->type]);
+ break;
+ case VVW_WIDGET_REFIT_VEH: // refit
+ ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
+ break;
+ case VVW_WIDGET_SHOW_ORDERS: // show orders
+ if (_ctrl_pressed) {
+ ShowTimetableWindow(v);
+ } else {
+ ShowOrdersWindow(v);
+ }
+ break;
+ case VVW_WIDGET_SHOW_DETAILS: // show details
+ ShowVehicleDetailsWindow(v);
+ break;
+ case VVW_WIDGET_CLONE_VEH: // clone vehicle
+ DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneVehicle,
+ _vehicle_command_translation_table[VCT_CMD_CLONE_VEH][v->type]);
+ break;
+ case VVW_WIDGET_TURN_AROUND: // turn around
+ assert(v->type == VEH_TRAIN || v->type == VEH_ROAD);
+ DoCommandP(v->tile, v->index, 0, NULL,
+ _vehicle_command_translation_table[VCT_CMD_TURN_AROUND][v->type]);
+ break;
+ case VVW_WIDGET_FORCE_PROCEED: // force proceed
+ assert(v->type == VEH_TRAIN);
+ DoCommandP(v->tile, v->index, 0, NULL, CMD_FORCE_TRAIN_PROCEED | CMD_MSG(STR_8862_CAN_T_MAKE_TRAIN_PASS_SIGNAL));
+ break;
+ }
+ }
+
+ virtual void OnResize(Point new_size, Point delta)
+ {
+ this->viewport->width += delta.x;
+ this->viewport->height += delta.y;
+ this->viewport->virtual_width += delta.x;
+ this->viewport->virtual_height += delta.y;
+ }
+
+ virtual void OnTick()
+ {
+ const Vehicle *v = GetVehicle(this->window_number);
+ bool veh_stopped = v->IsStoppedInDepot();
+
+ /* Widget VVW_WIDGET_GOTO_DEPOT must be hidden if the vehicle is already
+ * stopped in depot.
+ * Widget VVW_WIDGET_CLONE_VEH should then be shown, since cloning is
+ * allowed only while in depot and stopped.
+ * This sytem allows to have two buttons, on top of each other.
+ * The same system applies to widget VVW_WIDGET_REFIT_VEH and VVW_WIDGET_TURN_AROUND.*/
+ if (veh_stopped != this->IsWidgetHidden(VVW_WIDGET_GOTO_DEPOT) || veh_stopped == this->IsWidgetHidden(VVW_WIDGET_CLONE_VEH)) {
+ this->SetWidgetHiddenState( VVW_WIDGET_GOTO_DEPOT, veh_stopped); // send to depot
+ this->SetWidgetHiddenState(VVW_WIDGET_CLONE_VEH, !veh_stopped); // clone
+ if (v->type == VEH_ROAD || v->type == VEH_TRAIN) {
+ this->SetWidgetHiddenState( VVW_WIDGET_REFIT_VEH, !veh_stopped); // refit
+ this->SetWidgetHiddenState(VVW_WIDGET_TURN_AROUND, veh_stopped); // force turn around
}
- } break;
+ this->SetDirty();
+ }
}
+};
+
+
+/** Shows the vehicle view window of the given vehicle. */
+void ShowVehicleViewWindow(const Vehicle *v)
+{
+ AllocateWindowDescFront<VehicleViewWindow>((v->type == VEH_TRAIN) ? &_train_view_desc : &_vehicle_view_desc, v->index);
}
void DrawVehicleImage(const Vehicle *v, int x, int y, VehicleID selection, int count, int skip)
@@ -2177,3 +2114,12 @@
default: NOT_REACHED();
}
}
+
+void StopGlobalFollowVehicle(const Vehicle *v)
+{
+ Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
+ if (w != NULL && w->viewport->follow_vehicle == v->index) {
+ ScrollMainWindowTo(v->x_pos, v->y_pos, true); // lock the main view on the vehicle's last position
+ w->viewport->follow_vehicle = INVALID_VEHICLE;
+ }
+}