Merge remote-tracking branch 'upstream/master' into 13.0
This commit is contained in:
@@ -41,6 +41,7 @@
|
||||
#include "order_cmd.h"
|
||||
#include "roadveh_cmd.h"
|
||||
#include "train_cmd.h"
|
||||
#include "hotkeys.h"
|
||||
|
||||
#include "hotkeys.h"
|
||||
#include "citymania/cm_commands.hpp"
|
||||
@@ -143,6 +144,7 @@ const StringID BaseVehicleListWindow::vehicle_depot_name[] = {
|
||||
|
||||
BaseVehicleListWindow::BaseVehicleListWindow(WindowDesc *desc, WindowNumber wno) : Window(desc), vli(VehicleListIdentifier::UnPack(wno))
|
||||
{
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
this->grouping = _grouping[vli.type][vli.vtype];
|
||||
this->UpdateSortingFromGrouping();
|
||||
}
|
||||
@@ -199,6 +201,8 @@ void BaseVehicleListWindow::BuildVehicleList()
|
||||
max_unitnumber = std::max<uint>(max_unitnumber, (*it)->unitnumber);
|
||||
}
|
||||
this->unitnumber_digits = CountDigitsForAllocatingSpace(max_unitnumber);
|
||||
|
||||
this->FilterVehicleList();
|
||||
} else {
|
||||
/* Sort by the primary vehicle; we just want all vehicles that share the same orders to form a contiguous range. */
|
||||
std::stable_sort(this->vehicles.begin(), this->vehicles.end(), [](const Vehicle * const &u, const Vehicle * const &v) {
|
||||
@@ -227,6 +231,118 @@ void BaseVehicleListWindow::BuildVehicleList()
|
||||
this->vscroll->SetCount(static_cast<int>(this->vehgroups.size()));
|
||||
}
|
||||
|
||||
|
||||
/** Cargo filter functions */
|
||||
/**
|
||||
* Check whether a vehicle can carry a specific cargo.
|
||||
* @param vehgroup The vehicle group which contains the vehicle to be checked
|
||||
* @param cid The cargo what we are looking for
|
||||
* @return Whether the vehicle can carry the specified cargo or not
|
||||
*/
|
||||
static bool CDECL CargoFilter(const GUIVehicleGroup *vehgroup, const CargoID cid)
|
||||
{
|
||||
const Vehicle *v = (*vehgroup).GetSingleVehicle();
|
||||
if (cid == BaseVehicleListWindow::CF_ANY) {
|
||||
return true;
|
||||
} else if (cid == BaseVehicleListWindow::CF_NONE) {
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (cid == BaseVehicleListWindow::CF_FREIGHT) {
|
||||
bool have_capacity = false;
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0) {
|
||||
if (IsCargoInClass(w->cargo_type, CC_PASSENGERS)) {
|
||||
return false;
|
||||
} else {
|
||||
have_capacity = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return have_capacity;
|
||||
} else {
|
||||
for (const Vehicle *w = v; w != nullptr; w = w->Next()) {
|
||||
if (w->cargo_cap > 0 && w->cargo_type == cid) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static GUIVehicleGroupList::FilterFunction * const _filter_funcs[] = {
|
||||
&CargoFilter,
|
||||
};
|
||||
|
||||
/**
|
||||
* Set cargo filter list item index.
|
||||
* @param index The index to be set
|
||||
*/
|
||||
void BaseVehicleListWindow::SetCargoFilterIndex(byte index)
|
||||
{
|
||||
if (this->cargo_filter_criteria != index) {
|
||||
this->cargo_filter_criteria = index;
|
||||
/* Deactivate filter if criteria is 'Show All', activate it otherwise. */
|
||||
this->vehgroups.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
|
||||
this->vehgroups.SetFilterType(0);
|
||||
this->vehgroups.ForceRebuild();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*Populate the filter list and set the cargo filter criteria.
|
||||
*/
|
||||
void BaseVehicleListWindow::SetCargoFilterArray()
|
||||
{
|
||||
byte filter_items = 0;
|
||||
|
||||
/* Add item for disabling filtering. */
|
||||
this->cargo_filter[filter_items] = CF_ANY;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_ALL;
|
||||
this->cargo_filter_criteria = filter_items;
|
||||
filter_items++;
|
||||
|
||||
/* Add item for freight (i.e. vehicles with cargo capacity and with no passenger capacity). */
|
||||
this->cargo_filter[filter_items] = CF_FREIGHT;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_FREIGHT;
|
||||
filter_items++;
|
||||
|
||||
/* Add item for vehicles not carrying anything, e.g. train engines. */
|
||||
this->cargo_filter[filter_items] = CF_NONE;
|
||||
this->cargo_filter_texts[filter_items] = STR_CARGO_TYPE_FILTER_NONE;
|
||||
filter_items++;
|
||||
|
||||
/* Collect available cargo types for filtering. */
|
||||
for (const auto &cs : _sorted_cargo_specs) {
|
||||
this->cargo_filter[filter_items] = cs->Index();
|
||||
this->cargo_filter_texts[filter_items] = cs->name;
|
||||
filter_items++;
|
||||
}
|
||||
|
||||
/* Terminate the filter list. */
|
||||
this->cargo_filter_texts[filter_items] = INVALID_STRING_ID;
|
||||
|
||||
this->vehgroups.SetFilterFuncs(_filter_funcs);
|
||||
this->vehgroups.SetFilterState(this->cargo_filter[this->cargo_filter_criteria] != CF_ANY);
|
||||
}
|
||||
|
||||
/**
|
||||
*Filter the engine list against the currently selected cargo filter.
|
||||
*/
|
||||
void BaseVehicleListWindow::FilterVehicleList()
|
||||
{
|
||||
this->vehgroups.Filter(this->cargo_filter[this->cargo_filter_criteria]);
|
||||
if (this->vehicles.size() == 0) {
|
||||
/* No vehicle passed through the filter, invalidate the previously selected vehicle */
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
} else if (this->vehicle_sel != INVALID_VEHICLE && std::find(this->vehicles.begin(), this->vehicles.end(), Vehicle::Get(this->vehicle_sel)) == this->vehicles.end()) { // previously selected engine didn't pass the filter, remove selection
|
||||
this->vehicle_sel = INVALID_VEHICLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the size for the Action dropdown.
|
||||
* @param show_autoreplace If true include the autoreplace item.
|
||||
@@ -252,6 +368,7 @@ Dimension BaseVehicleListWindow::GetActionDropdownSize(bool show_autoreplace, bo
|
||||
void BaseVehicleListWindow::OnInit()
|
||||
{
|
||||
this->order_arrow_width = GetStringBoundingBox(STR_TINY_RIGHT_ARROW).width;
|
||||
this->SetCargoFilterArray();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -426,7 +543,7 @@ typedef std::vector<RefitOption> SubtypeList; ///< List of refit subtypes associ
|
||||
*/
|
||||
static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int sel[2], uint pos, uint rows, uint delta, const Rect &r)
|
||||
{
|
||||
uint y = r.top + WD_MATRIX_TOP;
|
||||
Rect ir = r.Shrink(WidgetDimensions::scaled.matrix);
|
||||
uint current = 0;
|
||||
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
@@ -434,12 +551,11 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
|
||||
uint iconheight = GetSpriteSize(SPR_CIRCLE_FOLDED).height;
|
||||
int linecolour = _colour_gradient[COLOUR_ORANGE][4];
|
||||
|
||||
int iconleft = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT;
|
||||
int iconcenter = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth / 2 : r.left + WD_MATRIX_LEFT + iconwidth / 2;
|
||||
int iconinner = rtl ? r.right - WD_MATRIX_RIGHT - iconwidth : r.left + WD_MATRIX_LEFT + iconwidth;
|
||||
int iconleft = rtl ? ir.right - iconwidth : ir.left;
|
||||
int iconcenter = rtl ? ir.right - iconwidth / 2 : ir.left + iconwidth / 2;
|
||||
int iconinner = rtl ? ir.right - iconwidth : ir.left + iconwidth;
|
||||
|
||||
int textleft = r.left + WD_MATRIX_LEFT + (rtl ? 0 : iconwidth + 4);
|
||||
int textright = r.right - WD_MATRIX_RIGHT - (rtl ? iconwidth + 4 : 0);
|
||||
Rect tr = ir.Indent(iconwidth + WidgetDimensions::scaled.hsep_wide, rtl);
|
||||
|
||||
/* Draw the list of subtypes for each cargo, and find the selected refit option (by its position). */
|
||||
for (uint i = 0; current < pos + rows && i < NUM_CARGO; i++) {
|
||||
@@ -458,12 +574,12 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
|
||||
if (list[i].size() > 1) {
|
||||
if (refit.subtype != 0xFF) {
|
||||
/* Draw tree lines */
|
||||
int ycenter = y + FONT_HEIGHT_NORMAL / 2;
|
||||
GfxDrawLine(iconcenter, y - WD_MATRIX_TOP, iconcenter, j == list[i].size() - 1 ? ycenter : y - WD_MATRIX_TOP + delta - 1, linecolour);
|
||||
int ycenter = tr.top + FONT_HEIGHT_NORMAL / 2;
|
||||
GfxDrawLine(iconcenter, tr.top - WidgetDimensions::scaled.matrix.top, iconcenter, j == list[i].size() - 1 ? ycenter : tr.top - WidgetDimensions::scaled.matrix.top + delta - 1, linecolour);
|
||||
GfxDrawLine(iconcenter, ycenter, iconinner, ycenter, linecolour);
|
||||
} else {
|
||||
/* Draw expand/collapse icon */
|
||||
DrawSprite(sel[0] == (int)i ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, y + (FONT_HEIGHT_NORMAL - iconheight) / 2);
|
||||
DrawSprite(sel[0] == (int)i ? SPR_CIRCLE_UNFOLDED : SPR_CIRCLE_FOLDED, PAL_NONE, iconleft, tr.top + (FONT_HEIGHT_NORMAL - iconheight) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,9 +587,9 @@ static void DrawVehicleRefitWindow(const SubtypeList list[NUM_CARGO], const int
|
||||
/* Get the cargo name. */
|
||||
SetDParam(0, CargoSpec::Get(refit.cargo)->name);
|
||||
SetDParam(1, refit.string);
|
||||
DrawString(textleft, textright, y, STR_JUST_STRING_STRING, colour);
|
||||
DrawString(tr, STR_JUST_STRING_STRING, colour);
|
||||
|
||||
y += delta;
|
||||
tr.top += delta;
|
||||
current++;
|
||||
}
|
||||
}
|
||||
@@ -752,7 +868,7 @@ struct RefitWindow : public Window {
|
||||
{
|
||||
switch (widget) {
|
||||
case WID_VR_MATRIX:
|
||||
resize->height = WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM;
|
||||
resize->height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
size->height = resize->height * 8;
|
||||
break;
|
||||
|
||||
@@ -761,7 +877,7 @@ struct RefitWindow : public Window {
|
||||
break;
|
||||
|
||||
case WID_VR_INFO:
|
||||
size->width = WD_FRAMERECT_LEFT + this->information_width + WD_FRAMERECT_RIGHT;
|
||||
size->width = this->information_width + padding.height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -821,8 +937,8 @@ struct RefitWindow : public Window {
|
||||
switch (widget) {
|
||||
case WID_VR_VEHICLE_PANEL_DISPLAY: {
|
||||
Vehicle *v = Vehicle::Get(this->window_number);
|
||||
DrawVehicleImage(v, this->sprite_left + WD_FRAMERECT_LEFT, this->sprite_right - WD_FRAMERECT_RIGHT,
|
||||
r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != nullptr ? this->hscroll->GetPosition() : 0);
|
||||
DrawVehicleImage(v, {this->sprite_left, r.top, this->sprite_right, r.bottom},
|
||||
INVALID_VEHICLE, EIT_IN_DETAILS, this->hscroll != nullptr ? this->hscroll->GetPosition() : 0);
|
||||
|
||||
/* Highlight selected vehicles. */
|
||||
if (this->order != INVALID_VEH_ORDER_ID) break;
|
||||
@@ -835,6 +951,11 @@ struct RefitWindow : public Window {
|
||||
int left = INT32_MIN;
|
||||
int width = 0;
|
||||
|
||||
/* Determine top & bottom position of the highlight.*/
|
||||
const int height = ScaleSpriteTrad(12);
|
||||
const int highlight_top = CenterBounds(r.top, r.bottom, height);
|
||||
const int highlight_bottom = highlight_top + height - 1;
|
||||
|
||||
for (Train *u = Train::From(v); u != nullptr; u = u->Next()) {
|
||||
/* Start checking. */
|
||||
const bool contained = std::find(vehicles_to_refit.begin(), vehicles_to_refit.end(), u->index) != vehicles_to_refit.end();
|
||||
@@ -855,12 +976,13 @@ struct RefitWindow : public Window {
|
||||
left = std::max(0, left);
|
||||
|
||||
if (_current_text_dir == TD_RTL) {
|
||||
right = this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->current_x - left;
|
||||
right = r.Width() - left;
|
||||
left = right - width;
|
||||
}
|
||||
|
||||
if (left != right) {
|
||||
DrawFrameRect(left, r.top + WD_FRAMERECT_TOP, right, r.top + WD_FRAMERECT_TOP + ScaleGUITrad(14) - 1, COLOUR_WHITE, FR_BORDERONLY);
|
||||
Rect hr = {left, highlight_top, right, highlight_bottom};
|
||||
DrawFrameRect(hr.Expand(WidgetDimensions::scaled.bevel), COLOUR_WHITE, FR_BORDERONLY);
|
||||
}
|
||||
|
||||
left = INT32_MIN;
|
||||
@@ -886,8 +1008,7 @@ struct RefitWindow : public Window {
|
||||
if (this->cargo != nullptr) {
|
||||
StringID string = this->GetCapacityString(this->cargo);
|
||||
if (string != INVALID_STRING_ID) {
|
||||
DrawStringMultiLine(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT,
|
||||
r.top + WD_FRAMERECT_TOP, r.bottom - WD_FRAMERECT_BOTTOM, string);
|
||||
DrawStringMultiLine(r.Shrink(WidgetDimensions::scaled.framerect), string);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1102,7 +1223,7 @@ static const NWidgetPart _nested_vehicle_refit_widgets[] = {
|
||||
NWidget(WWT_MATRIX, COLOUR_GREY, WID_VR_MATRIX), SetMinimalSize(228, 112), SetResize(1, 14), SetFill(1, 1), SetMatrixDataTip(1, 0, STR_NULL), SetScrollbar(WID_VR_SCROLLBAR),
|
||||
NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VR_SCROLLBAR),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_INFO), SetMinimalTextLines(2, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 0), EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_INFO), SetMinimalTextLines(2, WidgetDimensions::unscaled.framerect.Vertical()), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VR_REFIT), SetFill(1, 0), SetResize(1, 0),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
@@ -1387,15 +1508,23 @@ static const NWidgetPart _nested_vehicle_list[] = {
|
||||
EndContainer(),
|
||||
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VL_GROUP_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_GROUP_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(81, 12), SetFill(0, 1), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(167, 12), SetFill(0, 1), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(12, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VL_GROUP_ORDER), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_STATION_VIEW_GROUP, STR_TOOLTIP_GROUP_ORDER),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VL_SORT_ORDER), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(STR_BUTTON_SORT_BY, STR_TOOLTIP_SORT_ORDER),
|
||||
EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_GROUP_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_GROUP_ORDER),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_SORT_BY_PULLDOWN), SetMinimalSize(0, 12), SetFill(1, 0), SetDataTip(0x0, STR_TOOLTIP_SORT_CRITERIA),
|
||||
EndContainer(),
|
||||
NWidget(NWID_VERTICAL),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(NWID_SELECTION, INVALID_COLOUR, WID_VL_FILTER_BY_CARGO_SEL),
|
||||
NWidget(WWT_DROPDOWN, COLOUR_GREY, WID_VL_FILTER_BY_CARGO), SetMinimalSize(0, 12), SetFill(0, 0), SetDataTip(STR_JUST_STRING, STR_TOOLTIP_FILTER_CRITERIA),
|
||||
EndContainer(),
|
||||
NWidget(WWT_PANEL, COLOUR_GREY), SetMinimalSize(0, 12), SetFill(1, 1), SetResize(1, 0), EndContainer(),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
@@ -1476,19 +1605,17 @@ static void DrawSmallOrderList(const Order *order, int left, int right, int y, u
|
||||
/**
|
||||
* Draws an image of a vehicle chain
|
||||
* @param v Front vehicle
|
||||
* @param left The minimum horizontal position
|
||||
* @param right The maximum horizontal position
|
||||
* @param y Vertical position to draw at
|
||||
* @param r Rect to draw at
|
||||
* @param selection Selected vehicle to draw a frame around
|
||||
* @param skip Number of pixels to skip at the front (for scrolling)
|
||||
*/
|
||||
void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID selection, EngineImageType image_type, int skip)
|
||||
void DrawVehicleImage(const Vehicle *v, const Rect &r, VehicleID selection, EngineImageType image_type, int skip)
|
||||
{
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: DrawTrainImage(Train::From(v), left, right, y, selection, image_type, skip); break;
|
||||
case VEH_ROAD: DrawRoadVehImage(v, left, right, y, selection, image_type, skip); break;
|
||||
case VEH_SHIP: DrawShipImage(v, left, right, y, selection, image_type); break;
|
||||
case VEH_AIRCRAFT: DrawAircraftImage(v, left, right, y, selection, image_type); break;
|
||||
case VEH_TRAIN: DrawTrainImage(Train::From(v), r, selection, image_type, skip); break;
|
||||
case VEH_ROAD: DrawRoadVehImage(v, r, selection, image_type, skip); break;
|
||||
case VEH_SHIP: DrawShipImage(v, r, selection, image_type); break;
|
||||
case VEH_AIRCRAFT: DrawAircraftImage(v, r, selection, image_type); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
@@ -1502,9 +1629,9 @@ void DrawVehicleImage(const Vehicle *v, int left, int right, int y, VehicleID se
|
||||
uint GetVehicleListHeight(VehicleType type, uint divisor)
|
||||
{
|
||||
/* Name + vehicle + profit */
|
||||
uint base = ScaleGUITrad(GetVehicleHeight(type)) + 2 * FONT_HEIGHT_SMALL;
|
||||
uint base = ScaleGUITrad(GetVehicleHeight(type)) + 2 * FONT_HEIGHT_SMALL + WidgetDimensions::scaled.matrix.Vertical();
|
||||
/* Drawing of the 4 small orders + profit*/
|
||||
if (type >= VEH_SHIP) base = std::max(base, 5U * FONT_HEIGHT_SMALL);
|
||||
if (type >= VEH_SHIP) base = std::max(base, 5U * FONT_HEIGHT_SMALL + WidgetDimensions::scaled.matrix.Vertical());
|
||||
|
||||
if (divisor == 1) return base;
|
||||
|
||||
@@ -1521,25 +1648,21 @@ uint GetVehicleListHeight(VehicleType type, uint divisor)
|
||||
*/
|
||||
void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int line_height, const Rect &r) const
|
||||
{
|
||||
int left = r.left + WD_MATRIX_LEFT;
|
||||
int right = r.right - WD_MATRIX_RIGHT;
|
||||
int width = right - left;
|
||||
Rect ir = r.WithHeight(line_height).Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero);
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
|
||||
int text_offset = std::max<int>(GetSpriteSize(SPR_PROFIT_LOT).width, GetDigitWidth() * this->unitnumber_digits) + WD_FRAMERECT_RIGHT;
|
||||
int text_left = left + (rtl ? 0 : text_offset);
|
||||
int text_right = right - (rtl ? text_offset : 0);
|
||||
Dimension profit = GetSpriteSize(SPR_PROFIT_LOT);
|
||||
int text_offset = std::max<int>(profit.width, GetDigitWidth() * this->unitnumber_digits) + WidgetDimensions::scaled.hsep_normal;
|
||||
Rect tr = ir.Indent(text_offset, rtl);
|
||||
|
||||
bool show_orderlist = this->vli.vtype >= VEH_SHIP;
|
||||
int orderlist_left = left + (rtl ? 0 : std::max(ScaleGUITrad(100) + text_offset, width / 2));
|
||||
int orderlist_right = right - (rtl ? std::max(ScaleGUITrad(100) + text_offset, width / 2) : 0);
|
||||
Rect olr = ir.Indent(std::max(ScaleGUITrad(100) + text_offset, ir.Width() / 2), rtl);
|
||||
|
||||
int image_left = (rtl && show_orderlist) ? orderlist_right : text_left;
|
||||
int image_right = (!rtl && show_orderlist) ? orderlist_left : text_right;
|
||||
int image_left = (rtl && show_orderlist) ? olr.right : tr.left;
|
||||
int image_right = (!rtl && show_orderlist) ? olr.left : tr.right;
|
||||
|
||||
int vehicle_button_x = rtl ? right - GetSpriteSize(SPR_PROFIT_LOT).width : left;
|
||||
int vehicle_button_x = rtl ? ir.right - profit.width : ir.left;
|
||||
|
||||
int y = r.top;
|
||||
uint max = static_cast<uint>(std::min<size_t>(this->vscroll->GetPosition() + this->vscroll->GetCapacity(), this->vehgroups.size()));
|
||||
for (uint i = this->vscroll->GetPosition(); i < max; ++i) {
|
||||
|
||||
@@ -1547,31 +1670,60 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
||||
|
||||
SetDParam(0, vehgroup.GetDisplayProfitThisYear());
|
||||
SetDParam(1, vehgroup.GetDisplayProfitLastYear());
|
||||
DrawString(text_left, text_right, y + line_height - FONT_HEIGHT_SMALL - WD_FRAMERECT_BOTTOM - 1, STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
|
||||
DrawString(tr.left, tr.right, ir.bottom - FONT_HEIGHT_SMALL - WidgetDimensions::scaled.framerect.bottom, STR_VEHICLE_LIST_PROFIT_THIS_YEAR_LAST_YEAR);
|
||||
|
||||
DrawVehicleProfitButton(vehgroup.GetOldestVehicleAge(), vehgroup.GetDisplayProfitLastYear(), vehgroup.NumVehicles(), vehicle_button_x, y + FONT_HEIGHT_NORMAL + 3);
|
||||
DrawVehicleProfitButton(vehgroup.GetOldestVehicleAge(), vehgroup.GetDisplayProfitLastYear(), vehgroup.NumVehicles(), vehicle_button_x, ir.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal);
|
||||
|
||||
switch (this->grouping) {
|
||||
case GB_NONE: {
|
||||
const Vehicle *v = vehgroup.GetSingleVehicle();
|
||||
|
||||
if (HasBit(v->vehicle_flags, VF_PATHFINDER_LOST)) {
|
||||
DrawSprite(SPR_WARNING_SIGN, PAL_NONE, vehicle_button_x, y + FONT_HEIGHT_NORMAL + 3 + GetSpriteSize(SPR_PROFIT_LOT).height);
|
||||
DrawSprite(SPR_WARNING_SIGN, PAL_NONE, vehicle_button_x, ir.top + FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal + profit.height);
|
||||
}
|
||||
|
||||
DrawVehicleImage(v, image_left, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
|
||||
DrawVehicleImage(v, {image_left, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0);
|
||||
|
||||
if (!v->name.empty()) {
|
||||
if (_settings_client.gui.show_cargo_in_vehicle_lists) {
|
||||
/* Get the cargoes the vehicle can carry */
|
||||
CargoTypes vehicle_cargoes = 0;
|
||||
|
||||
for (auto u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->cargo_cap == 0) continue;
|
||||
|
||||
SetBit(vehicle_cargoes, u->cargo_type);
|
||||
}
|
||||
|
||||
if (!v->name.empty()) {
|
||||
/* The vehicle got a name so we will print it and the cargoes */
|
||||
SetDParam(0, STR_TINY_BLACK_VEHICLE);
|
||||
SetDParam(1, v->index);
|
||||
SetDParam(2, STR_VEHICLE_LIST_CARGO);
|
||||
SetDParam(3, vehicle_cargoes);
|
||||
DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_NAME_AND_CARGO);
|
||||
} else if (v->group_id != DEFAULT_GROUP) {
|
||||
/* The vehicle has no name, but is member of a group, so print group name and the cargoes */
|
||||
SetDParam(0, STR_TINY_GROUP);
|
||||
SetDParam(1, v->group_id);
|
||||
SetDParam(2, STR_VEHICLE_LIST_CARGO);
|
||||
SetDParam(3, vehicle_cargoes);
|
||||
DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_NAME_AND_CARGO);
|
||||
} else {
|
||||
/* The vehicle has no name, and is not a member of a group, so just print the cargoes */
|
||||
SetDParam(0, vehicle_cargoes);
|
||||
DrawString(tr.left, tr.right, ir.top, STR_VEHICLE_LIST_CARGO);
|
||||
}
|
||||
} else if (!v->name.empty()) {
|
||||
/* The vehicle got a name so we will print it */
|
||||
SetDParam(0, v->index);
|
||||
DrawString(text_left, text_right, y, STR_TINY_BLACK_VEHICLE);
|
||||
DrawString(tr.left, tr.right, ir.top, STR_TINY_BLACK_VEHICLE);
|
||||
} else if (v->group_id != DEFAULT_GROUP) {
|
||||
/* The vehicle has no name, but is member of a group, so print group name */
|
||||
SetDParam(0, v->group_id);
|
||||
DrawString(text_left, text_right, y, STR_TINY_GROUP, TC_BLACK);
|
||||
DrawString(tr.left, tr.right, ir.top, STR_TINY_GROUP, TC_BLACK);
|
||||
}
|
||||
|
||||
if (show_orderlist) DrawSmallOrderList(v, orderlist_left, orderlist_right, y, this->order_arrow_width, v->cur_real_order_index);
|
||||
if (show_orderlist) DrawSmallOrderList(v, olr.left, olr.right, ir.top, this->order_arrow_width, v->cur_real_order_index);
|
||||
|
||||
StringID str;
|
||||
if (v->IsChainInDepot()) {
|
||||
@@ -1581,7 +1733,7 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
||||
}
|
||||
|
||||
SetDParam(0, v->unitnumber);
|
||||
DrawString(left, right, y + 2, str);
|
||||
DrawString(ir.left, ir.right, ir.top + WidgetDimensions::scaled.framerect.top, str);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1589,21 +1741,21 @@ void BaseVehicleListWindow::DrawVehicleListItems(VehicleID selected_vehicle, int
|
||||
assert(vehgroup.NumVehicles() > 0);
|
||||
|
||||
for (int i = 0; i < static_cast<int>(vehgroup.NumVehicles()); ++i) {
|
||||
if (image_left + 8 * i >= image_right) break; // Break if there is no more space to draw any more vehicles anyway.
|
||||
DrawVehicleImage(vehgroup.vehicles_begin[i], image_left + 8 * i, image_right, y + FONT_HEIGHT_SMALL - 1, selected_vehicle, EIT_IN_LIST, 0);
|
||||
if (image_left + WidgetDimensions::scaled.hsep_wide * i >= image_right) break; // Break if there is no more space to draw any more vehicles anyway.
|
||||
DrawVehicleImage(vehgroup.vehicles_begin[i], {image_left + WidgetDimensions::scaled.hsep_wide * i, ir.top, image_right, ir.bottom}, selected_vehicle, EIT_IN_LIST, 0);
|
||||
}
|
||||
|
||||
if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), orderlist_left, orderlist_right, y, this->order_arrow_width);
|
||||
if (show_orderlist) DrawSmallOrderList((vehgroup.vehicles_begin[0])->GetFirstOrder(), olr.left, olr.right, ir.top, this->order_arrow_width);
|
||||
|
||||
SetDParam(0, vehgroup.NumVehicles());
|
||||
DrawString(left, right, y + 2, STR_BLACK_COMMA);
|
||||
DrawString(ir.left, ir.right, ir.top + WidgetDimensions::scaled.framerect.top, STR_BLACK_COMMA);
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
y += line_height;
|
||||
ir = ir.Translate(0, line_height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1666,6 +1818,8 @@ public:
|
||||
{
|
||||
this->CreateNestedTree();
|
||||
|
||||
this->GetWidget<NWidgetStacked>(WID_VL_FILTER_BY_CARGO_SEL)->SetDisplayedPlane((this->vli.type == VL_SHARED_ORDERS) ? SZSP_NONE : 0);
|
||||
|
||||
this->vscroll = this->GetScrollbar(WID_VL_SCROLLBAR);
|
||||
|
||||
this->BuildVehicleList();
|
||||
@@ -1723,6 +1877,20 @@ public:
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_VL_GROUP_BY_PULLDOWN:
|
||||
size->width = GetStringListWidth(this->vehicle_group_by_names) + padding.width;
|
||||
break;
|
||||
|
||||
case WID_VL_SORT_BY_PULLDOWN:
|
||||
size->width = GetStringListWidth(this->vehicle_group_none_sorter_names);
|
||||
size->width = std::max(size->width, GetStringListWidth(this->vehicle_group_shared_orders_sorter_names));
|
||||
size->width += padding.width;
|
||||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
size->width = GetStringListWidth(this->cargo_filter_texts) + padding.width;
|
||||
break;
|
||||
|
||||
case WID_VL_MANAGE_VEHICLES_DROPDOWN: {
|
||||
Dimension d = this->GetActionDropdownSize(this->vli.type == VL_STANDARD, false);
|
||||
d.height += padding.height;
|
||||
@@ -1740,6 +1908,10 @@ public:
|
||||
SetDParam(0, STR_VEHICLE_LIST_AVAILABLE_TRAINS + this->vli.vtype);
|
||||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
SetDParam(0, this->cargo_filter_texts[this->cargo_filter_criteria]);
|
||||
break;
|
||||
|
||||
case WID_VL_CAPTION:
|
||||
case WID_VL_CAPTION_SHARED_ORDERS: {
|
||||
switch (this->vli.type) {
|
||||
@@ -1823,6 +1995,8 @@ public:
|
||||
/* Set text of sort by dropdown widget. */
|
||||
this->GetWidget<NWidgetCore>(WID_VL_SORT_BY_PULLDOWN)->widget_data = this->GetVehicleSorterNames()[this->vehgroups.SortType()];
|
||||
|
||||
this->GetWidget<NWidgetCore>(WID_VL_FILTER_BY_CARGO)->widget_data = this->cargo_filter_texts[this->cargo_filter_criteria];
|
||||
|
||||
this->DrawWidgets();
|
||||
}
|
||||
|
||||
@@ -1849,6 +2023,10 @@ public:
|
||||
(this->vli.vtype == VEH_TRAIN || this->vli.vtype == VEH_ROAD) ? 0 : (1 << 10));
|
||||
return;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO: // Cargo filter dropdown
|
||||
ShowDropDownMenu(this, this->cargo_filter_texts, this->cargo_filter_criteria, WID_VL_FILTER_BY_CARGO, 0, 0);
|
||||
break;
|
||||
|
||||
case WID_VL_LIST: { // Matrix to show vehicles
|
||||
uint id_v = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VL_LIST);
|
||||
if (id_v >= this->vehgroups.size()) return; // click out of list bound
|
||||
@@ -1869,16 +2047,16 @@ public:
|
||||
|
||||
case GB_SHARED_ORDERS: {
|
||||
assert(vehgroup.NumVehicles() > 0);
|
||||
const Vehicle *v = vehgroup.vehicles_begin[0];
|
||||
/* We do not support VehicleClicked() here since the contextual action may only make sense for individual vehicles */
|
||||
|
||||
if (_ctrl_pressed) {
|
||||
ShowOrdersWindow(v);
|
||||
} else {
|
||||
if (vehgroup.NumVehicles() == 1) {
|
||||
ShowVehicleViewWindow(v);
|
||||
if (!VehicleClicked(vehgroup)) {
|
||||
const Vehicle *v = vehgroup.vehicles_begin[0];
|
||||
if (_ctrl_pressed) {
|
||||
ShowOrdersWindow(v);
|
||||
} else {
|
||||
ShowVehicleListWindow(v);
|
||||
if (vehgroup.NumVehicles() == 1) {
|
||||
ShowVehicleViewWindow(v);
|
||||
} else {
|
||||
ShowVehicleListWindow(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1917,6 +2095,10 @@ public:
|
||||
this->vehgroups.SetSortType(index);
|
||||
break;
|
||||
|
||||
case WID_VL_FILTER_BY_CARGO:
|
||||
this->SetCargoFilterIndex(index);
|
||||
break;
|
||||
|
||||
case WID_VL_MANAGE_VEHICLES_DROPDOWN:
|
||||
assert(this->vehicles.size() != 0);
|
||||
|
||||
@@ -2109,10 +2291,10 @@ static const NWidgetPart _nested_train_vehicle_details_widgets[] = {
|
||||
|
||||
|
||||
extern int GetTrainDetailsWndVScroll(VehicleID veh_id, TrainDetailsWindowTabs det_tab);
|
||||
extern void DrawTrainDetails(const Train *v, int left, int right, int y, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab);
|
||||
extern void DrawRoadVehDetails(const Vehicle *v, int left, int right, int y);
|
||||
extern void DrawShipDetails(const Vehicle *v, int left, int right, int y);
|
||||
extern void DrawAircraftDetails(const Aircraft *v, int left, int right, int y);
|
||||
extern void DrawTrainDetails(const Train *v, const Rect &r, int vscroll_pos, uint16 vscroll_cap, TrainDetailsWindowTabs det_tab);
|
||||
extern void DrawRoadVehDetails(const Vehicle *v, const Rect &r);
|
||||
extern void DrawShipDetails(const Vehicle *v, const Rect &r);
|
||||
extern void DrawAircraftDetails(const Aircraft *v, const Rect &r);
|
||||
|
||||
static StringID _service_interval_dropdown[] = {
|
||||
STR_VEHICLE_DETAILS_DEFAULT,
|
||||
@@ -2173,13 +2355,13 @@ struct VehicleDetailsWindow : Window {
|
||||
uint desired_height;
|
||||
if (v->HasArticulatedPart()) {
|
||||
/* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */
|
||||
desired_height = WD_FRAMERECT_TOP + ScaleGUITrad(15) + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM;
|
||||
desired_height = ScaleGUITrad(15) + 3 * FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal * 2;
|
||||
/* Add space for the cargo amount for each part. */
|
||||
for (const Vehicle *u = v; u != nullptr; u = u->Next()) {
|
||||
if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1;
|
||||
if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL;
|
||||
}
|
||||
} else {
|
||||
desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
|
||||
desired_height = 4 * FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal * 2;
|
||||
}
|
||||
return desired_height;
|
||||
}
|
||||
@@ -2189,7 +2371,7 @@ struct VehicleDetailsWindow : Window {
|
||||
switch (widget) {
|
||||
case WID_VD_TOP_DETAILS: {
|
||||
Dimension dim = { 0, 0 };
|
||||
size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
|
||||
size->height = 4 * FONT_HEIGHT_NORMAL + padding.height;
|
||||
|
||||
for (uint i = 0; i < 4; i++) SetDParamMaxValue(i, INT16_MAX);
|
||||
static const StringID info_strings[] = {
|
||||
@@ -2204,7 +2386,7 @@ struct VehicleDetailsWindow : Window {
|
||||
}
|
||||
SetDParam(0, STR_VEHICLE_INFO_AGE);
|
||||
dim = maxdim(dim, GetStringBoundingBox(STR_VEHICLE_INFO_AGE_RUNNING_COST_YR));
|
||||
size->width = dim.width + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
size->width = dim.width + padding.width;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2212,15 +2394,15 @@ struct VehicleDetailsWindow : Window {
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
switch (v->type) {
|
||||
case VEH_ROAD:
|
||||
size->height = this->GetRoadVehDetailsHeight(v);
|
||||
size->height = this->GetRoadVehDetailsHeight(v) + padding.height;
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM;
|
||||
size->height = 4 * FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal * 2 + padding.height;
|
||||
break;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
size->height = WD_FRAMERECT_TOP + 5 * FONT_HEIGHT_NORMAL + 4 + WD_FRAMERECT_BOTTOM;
|
||||
size->height = 5 * FONT_HEIGHT_NORMAL + WidgetDimensions::scaled.vsep_normal * 2 + padding.height;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -2230,7 +2412,7 @@ struct VehicleDetailsWindow : Window {
|
||||
}
|
||||
|
||||
case WID_VD_MATRIX:
|
||||
resize->height = std::max(ScaleGUITrad(14), WD_MATRIX_TOP + FONT_HEIGHT_NORMAL + WD_MATRIX_BOTTOM);
|
||||
resize->height = std::max<uint>(ScaleGUITrad(14), FONT_HEIGHT_NORMAL + padding.height);
|
||||
size->height = 4 * resize->height;
|
||||
break;
|
||||
|
||||
@@ -2240,7 +2422,7 @@ struct VehicleDetailsWindow : Window {
|
||||
*size = maxdim(*size, GetStringBoundingBox(*strs++));
|
||||
}
|
||||
size->width += padding.width;
|
||||
size->height = FONT_HEIGHT_NORMAL + WD_DROPDOWNTEXT_TOP + WD_DROPDOWNTEXT_BOTTOM;
|
||||
size->height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2250,8 +2432,8 @@ struct VehicleDetailsWindow : Window {
|
||||
size->width = std::max(
|
||||
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT).width,
|
||||
GetStringBoundingBox(STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS).width
|
||||
) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
size->height = WD_FRAMERECT_TOP + FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM;
|
||||
) + padding.width;
|
||||
size->height = FONT_HEIGHT_NORMAL + padding.height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2273,20 +2455,18 @@ struct VehicleDetailsWindow : Window {
|
||||
* Draw the details for the given vehicle at the position of the Details windows
|
||||
*
|
||||
* @param v current vehicle
|
||||
* @param left The left most coordinate to draw
|
||||
* @param right The right most coordinate to draw
|
||||
* @param y The y coordinate
|
||||
* @param r the Rect to draw within
|
||||
* @param vscroll_pos Position of scrollbar (train only)
|
||||
* @param vscroll_cap Number of lines currently displayed (train only)
|
||||
* @param det_tab Selected details tab (train only)
|
||||
*/
|
||||
static void DrawVehicleDetails(const Vehicle *v, int left, int right, int y, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
|
||||
static void DrawVehicleDetails(const Vehicle *v, const Rect &r, int vscroll_pos, uint vscroll_cap, TrainDetailsWindowTabs det_tab)
|
||||
{
|
||||
switch (v->type) {
|
||||
case VEH_TRAIN: DrawTrainDetails(Train::From(v), left, right, y, vscroll_pos, vscroll_cap, det_tab); break;
|
||||
case VEH_ROAD: DrawRoadVehDetails(v, left, right, y); break;
|
||||
case VEH_SHIP: DrawShipDetails(v, left, right, y); break;
|
||||
case VEH_AIRCRAFT: DrawAircraftDetails(Aircraft::From(v), left, right, y); break;
|
||||
case VEH_TRAIN: DrawTrainDetails(Train::From(v), r, vscroll_pos, vscroll_cap, det_tab); break;
|
||||
case VEH_ROAD: DrawRoadVehDetails(v, r); break;
|
||||
case VEH_SHIP: DrawShipDetails(v, r); break;
|
||||
case VEH_AIRCRAFT: DrawAircraftDetails(Aircraft::From(v), r); break;
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
@@ -2302,15 +2482,15 @@ struct VehicleDetailsWindow : Window {
|
||||
|
||||
switch (widget) {
|
||||
case WID_VD_TOP_DETAILS: {
|
||||
int y = r.top + WD_FRAMERECT_TOP;
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||
|
||||
/* Draw running cost */
|
||||
SetDParam(1, v->age / DAYS_IN_LEAP_YEAR);
|
||||
SetDParam(0, (v->age + DAYS_IN_YEAR < v->max_age) ? STR_VEHICLE_INFO_AGE : STR_VEHICLE_INFO_AGE_RED);
|
||||
SetDParam(2, v->max_age / DAYS_IN_LEAP_YEAR);
|
||||
SetDParam(3, v->GetDisplayRunningCost());
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
DrawString(tr, STR_VEHICLE_INFO_AGE_RUNNING_COST_YR);
|
||||
tr.top += FONT_HEIGHT_NORMAL;
|
||||
|
||||
/* Draw max speed */
|
||||
StringID string;
|
||||
@@ -2341,55 +2521,60 @@ struct VehicleDetailsWindow : Window {
|
||||
string = STR_VEHICLE_INFO_MAX_SPEED;
|
||||
}
|
||||
}
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, string);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
DrawString(tr, string);
|
||||
tr.top += FONT_HEIGHT_NORMAL;
|
||||
|
||||
/* Draw profit */
|
||||
SetDParam(0, v->GetDisplayProfitThisYear());
|
||||
SetDParam(1, v->GetDisplayProfitLastYear());
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR);
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
if (v->IsGroundVehicle()) {
|
||||
SetDParam(2, v->GetDisplayMinPowerToWeight());
|
||||
DrawString(tr, STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR_MIN_PERFORMANCE);
|
||||
} else {
|
||||
DrawString(tr, STR_VEHICLE_INFO_PROFIT_THIS_YEAR_LAST_YEAR);
|
||||
}
|
||||
tr.top += FONT_HEIGHT_NORMAL;
|
||||
|
||||
/* Draw breakdown & reliability */
|
||||
SetDParam(0, ToPercent16(v->reliability));
|
||||
SetDParam(1, v->breakdowns_since_last_service);
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, y, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
|
||||
DrawString(tr, STR_VEHICLE_INFO_RELIABILITY_BREAKDOWNS);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_VD_MATRIX:
|
||||
case WID_VD_MATRIX: {
|
||||
/* For trains only. */
|
||||
DrawVehicleDetails(v, r.left + WD_MATRIX_LEFT, r.right - WD_MATRIX_RIGHT, r.top + WD_MATRIX_TOP, this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->tab);
|
||||
DrawVehicleDetails(v, r.Shrink(WidgetDimensions::scaled.matrix, RectPadding::zero).WithHeight(this->resize.step_height), this->vscroll->GetPosition(), this->vscroll->GetCapacity(), this->tab);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_VD_MIDDLE_DETAILS: {
|
||||
/* For other vehicles, at the place of the matrix. */
|
||||
bool rtl = _current_text_dir == TD_RTL;
|
||||
uint sprite_width = GetSingleVehicleWidth(v, EIT_IN_DETAILS) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
|
||||
|
||||
uint text_left = r.left + (rtl ? 0 : sprite_width);
|
||||
uint text_right = r.right - (rtl ? sprite_width : 0);
|
||||
uint sprite_width = GetSingleVehicleWidth(v, EIT_IN_DETAILS) + WidgetDimensions::scaled.framerect.Horizontal();
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||
|
||||
/* Articulated road vehicles use a complete line. */
|
||||
if (v->type == VEH_ROAD && v->HasArticulatedPart()) {
|
||||
DrawVehicleImage(v, r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
|
||||
DrawVehicleImage(v, tr.WithHeight(ScaleGUITrad(GetVehicleHeight(v->type)), false), INVALID_VEHICLE, EIT_IN_DETAILS, 0);
|
||||
} else {
|
||||
uint sprite_left = rtl ? text_right : r.left;
|
||||
uint sprite_right = rtl ? r.right : text_left;
|
||||
|
||||
DrawVehicleImage(v, sprite_left + WD_FRAMERECT_LEFT, sprite_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, INVALID_VEHICLE, EIT_IN_DETAILS, 0);
|
||||
Rect sr = tr.WithWidth(sprite_width, rtl);
|
||||
DrawVehicleImage(v, sr.WithHeight(ScaleGUITrad(GetVehicleHeight(v->type)), false), INVALID_VEHICLE, EIT_IN_DETAILS, 0);
|
||||
}
|
||||
DrawVehicleDetails(v, text_left + WD_FRAMERECT_LEFT, text_right - WD_FRAMERECT_RIGHT, r.top + WD_FRAMERECT_TOP, 0, 0, this->tab);
|
||||
|
||||
DrawVehicleDetails(v, tr.Indent(sprite_width, rtl), 0, 0, this->tab);
|
||||
break;
|
||||
}
|
||||
|
||||
case WID_VD_SERVICING_INTERVAL:
|
||||
case WID_VD_SERVICING_INTERVAL: {
|
||||
/* Draw service interval text */
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
|
||||
SetDParam(0, v->GetServiceInterval());
|
||||
SetDParam(1, v->date_of_last_service);
|
||||
DrawString(r.left + WD_FRAMERECT_LEFT, r.right - WD_FRAMERECT_RIGHT, r.top + (r.bottom - r.top + 1 - FONT_HEIGHT_NORMAL) / 2,
|
||||
DrawString(tr.left, tr.right, CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL),
|
||||
v->ServiceIntervalIsPercent() ? STR_VEHICLE_DETAILS_SERVICING_INTERVAL_PERCENT : STR_VEHICLE_DETAILS_SERVICING_INTERVAL_DAYS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2399,7 +2584,7 @@ struct VehicleDetailsWindow : Window {
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
|
||||
if (v->type == VEH_TRAIN) {
|
||||
this->DisableWidget(this->tab + WID_VD_DETAILS_CARGO_CARRIED);
|
||||
this->LowerWidget(this->tab + WID_VD_DETAILS_CARGO_CARRIED);
|
||||
this->vscroll->SetCount(GetTrainDetailsWndVScroll(v->index, this->tab));
|
||||
}
|
||||
|
||||
@@ -2443,7 +2628,7 @@ struct VehicleDetailsWindow : Window {
|
||||
case WID_VD_DETAILS_TRAIN_VEHICLES:
|
||||
case WID_VD_DETAILS_CAPACITY_OF_EACH:
|
||||
case WID_VD_DETAILS_TOTAL_CARGO:
|
||||
this->SetWidgetsDisabledState(false,
|
||||
this->SetWidgetsLoweredState(false,
|
||||
WID_VD_DETAILS_CARGO_CARRIED,
|
||||
WID_VD_DETAILS_TRAIN_VEHICLES,
|
||||
WID_VD_DETAILS_CAPACITY_OF_EACH,
|
||||
@@ -2544,7 +2729,7 @@ static const NWidgetPart _nested_vehicle_view_widgets[] = {
|
||||
EndContainer(),
|
||||
EndContainer(),
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_VV_START_STOP), SetMinimalTextLines(1, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM + 2), SetResize(1, 0), SetFill(1, 0),
|
||||
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_VV_START_STOP), SetResize(1, 0), SetFill(1, 0),
|
||||
NWidget(WWT_PUSHIMGBTN, COLOUR_GREY, WID_VV_ORDER_LOCATION), SetMinimalSize(12, 14), SetDataTip(SPR_GOTO_LOCATION, STR_VEHICLE_VIEW_ORDER_LOCATION_TOOLTIP),
|
||||
NWidget(WWT_RESIZEBOX, COLOUR_GREY),
|
||||
EndContainer(),
|
||||
@@ -2761,7 +2946,7 @@ public:
|
||||
const Vehicle *v = Vehicle::Get(this->window_number);
|
||||
switch (widget) {
|
||||
case WID_VV_START_STOP:
|
||||
size->height = std::max({size->height, GetSpriteSize(SPR_WARNING_SIGN).height, GetSpriteSize(SPR_FLAG_VEH_STOPPED).height, GetSpriteSize(SPR_FLAG_VEH_RUNNING).height}) + WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM;
|
||||
size->height = std::max<uint>({size->height, (uint)FONT_HEIGHT_NORMAL, GetScaledSpriteSize(SPR_WARNING_SIGN).height, GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED).height, GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING).height}) + padding.height;
|
||||
break;
|
||||
|
||||
case WID_VV_FORCE_PROCEED:
|
||||
@@ -2908,17 +3093,13 @@ public:
|
||||
|
||||
/* Draw the flag plus orders. */
|
||||
bool rtl = (_current_text_dir == TD_RTL);
|
||||
uint text_offset = std::max({GetSpriteSize(SPR_WARNING_SIGN).width, GetSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetSpriteSize(SPR_FLAG_VEH_RUNNING).width}) + WD_IMGBTN_LEFT + WD_IMGBTN_RIGHT;
|
||||
int height = r.bottom - r.top;
|
||||
int text_left = r.left + (rtl ? (uint)WD_FRAMERECT_LEFT : text_offset);
|
||||
int text_right = r.right - (rtl ? text_offset : (uint)WD_FRAMERECT_RIGHT);
|
||||
int text_top = r.top + WD_FRAMERECT_TOP + (height - WD_FRAMERECT_TOP - WD_FRAMERECT_BOTTOM - FONT_HEIGHT_NORMAL) / 2;
|
||||
int image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : (HasBit(v->vehicle_flags, VF_PATHFINDER_LOST)) ? SPR_WARNING_SIGN : SPR_FLAG_VEH_RUNNING;
|
||||
int image_left = (rtl ? text_right + 1 : r.left) + WD_IMGBTN_LEFT;
|
||||
int image_top = r.top + WD_IMGBTN_TOP + (height - WD_IMGBTN_TOP + WD_IMGBTN_BOTTOM - GetSpriteSize(image).height) / 2;
|
||||
int lowered = this->IsWidgetLowered(WID_VV_START_STOP) ? 1 : 0;
|
||||
DrawSprite(image, PAL_NONE, image_left + lowered, image_top + lowered);
|
||||
DrawString(text_left + lowered, text_right + lowered, text_top + lowered, str, text_colour, SA_HOR_CENTER);
|
||||
uint icon_width = std::max({GetScaledSpriteSize(SPR_WARNING_SIGN).width, GetScaledSpriteSize(SPR_FLAG_VEH_STOPPED).width, GetScaledSpriteSize(SPR_FLAG_VEH_RUNNING).width});
|
||||
int lowered = this->IsWidgetLowered(widget) ? WidgetDimensions::scaled.pressed : 0;
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect).Translate(lowered, lowered);
|
||||
SpriteID image = ((v->vehstatus & VS_STOPPED) != 0) ? SPR_FLAG_VEH_STOPPED : (HasBit(v->vehicle_flags, VF_PATHFINDER_LOST)) ? SPR_WARNING_SIGN : SPR_FLAG_VEH_RUNNING;
|
||||
DrawSpriteIgnorePadding(image, PAL_NONE, tr.WithWidth(icon_width, rtl), false, SA_CENTER);
|
||||
tr = tr.Indent(icon_width + WidgetDimensions::scaled.imgbtn.Horizontal(), rtl);
|
||||
DrawString(tr.left, tr.right, CenterBounds(tr.top, tr.bottom, FONT_HEIGHT_NORMAL), str, text_colour, SA_HOR_CENTER);
|
||||
}
|
||||
|
||||
void OnClick(Point pt, int widget, int click_count) override
|
||||
@@ -3008,6 +3189,22 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
EventState OnHotkey(int hotkey) override
|
||||
{
|
||||
/* If the hotkey is not for any widget in the UI (i.e. for honking) */
|
||||
if (hotkey == WID_VV_HONK_HORN) {
|
||||
const Window* mainwindow = FindWindowById(WC_MAIN_WINDOW, 0);
|
||||
const Vehicle* v = Vehicle::Get(window_number);
|
||||
/*Only play the sound if we're following this vehicle */
|
||||
if (mainwindow->viewport->follow_vehicle == v->index) {
|
||||
v->PlayLeaveStationSound(true);
|
||||
}
|
||||
} else {
|
||||
if (this->owner != _local_company) return ES_NOT_HANDLED;
|
||||
}
|
||||
return Window::OnHotkey(hotkey);
|
||||
}
|
||||
|
||||
void OnQueryTextFinished(char *str) override
|
||||
{
|
||||
if (str == nullptr) return;
|
||||
@@ -3083,23 +3280,18 @@ public:
|
||||
::ShowNewGRFInspectWindow(GetGrfSpecFeature(Vehicle::Get(this->window_number)->type), this->window_number);
|
||||
}
|
||||
|
||||
virtual EventState OnHotkey(int hotkey)
|
||||
{
|
||||
if (this->owner != _local_company) return ES_NOT_HANDLED;
|
||||
return Window::OnHotkey(hotkey);
|
||||
}
|
||||
|
||||
static HotkeyList hotkeys;
|
||||
};
|
||||
|
||||
static Hotkey vehiclegui_hotkeys[] = {
|
||||
static Hotkey vehicleview_hotkeys[] = {
|
||||
Hotkey('H', "honk", WID_VV_HONK_HORN),
|
||||
Hotkey('G', "vehicle_orders", WID_VV_SHOW_ORDERS),
|
||||
Hotkey('F', "vehicle_go", WID_VV_START_STOP),
|
||||
Hotkey((uint16)0, "vehicle_refit", WID_VV_REFIT),
|
||||
Hotkey((uint16)0, "vehicle_clone", WID_VV_CLONE),
|
||||
HOTKEY_LIST_END
|
||||
};
|
||||
HotkeyList VehicleViewWindow::hotkeys("vehiclegui", vehiclegui_hotkeys);
|
||||
HotkeyList VehicleViewWindow::hotkeys("vehicleview", vehicleview_hotkeys);
|
||||
|
||||
/** Vehicle view window descriptor for all vehicles but trains. */
|
||||
static WindowDesc _vehicle_view_desc(
|
||||
@@ -3144,6 +3336,33 @@ bool VehicleClicked(const Vehicle *v)
|
||||
return _thd.GetCallbackWnd()->OnVehicleSelect(v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a "vehicle group selected" event if any window waits for it.
|
||||
* @param begin iterator to the start of the range of vehicles
|
||||
* @param end iterator to the end of the range of vehicles
|
||||
* @return did any window accept vehicle group selection?
|
||||
*/
|
||||
bool VehicleClicked(VehicleList::const_iterator begin, VehicleList::const_iterator end)
|
||||
{
|
||||
assert(begin != end);
|
||||
if (!(_thd.place_mode & HT_VEHICLE)) return false;
|
||||
|
||||
/* If there is only one vehicle in the group, act as if we clicked a single vehicle */
|
||||
if (begin + 1 == end) return _thd.GetCallbackWnd()->OnVehicleSelect(*begin);
|
||||
|
||||
return _thd.GetCallbackWnd()->OnVehicleSelect(begin, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a "vehicle group selected" event if any window waits for it.
|
||||
* @param vehgroup the GUIVehicleGroup representing the vehicle group
|
||||
* @return did any window accept vehicle group selection?
|
||||
*/
|
||||
bool VehicleClicked(const GUIVehicleGroup &vehgroup)
|
||||
{
|
||||
return VehicleClicked(vehgroup.vehicles_begin, vehgroup.vehicles_end);
|
||||
}
|
||||
|
||||
void StopGlobalFollowVehicle(const Vehicle *v)
|
||||
{
|
||||
Window *w = FindWindowById(WC_MAIN_WINDOW, 0);
|
||||
@@ -3191,7 +3410,7 @@ int GetSingleVehicleWidth(const Vehicle *v, EngineImageType image_type)
|
||||
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
|
||||
Rect rec;
|
||||
seq.GetBounds(&rec);
|
||||
return UnScaleGUI(rec.right - rec.left + 1);
|
||||
return UnScaleGUI(rec.Width());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3229,7 +3448,7 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
|
||||
bool is_ground_vehicle = v->IsGroundVehicle();
|
||||
|
||||
while (v != nullptr) {
|
||||
if (total_width >= ScaleGUITrad(2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH)) break;
|
||||
if (total_width >= ScaleSpriteTrad(2 * (int)VEHICLEINFO_FULL_VEHICLE_WIDTH)) break;
|
||||
|
||||
PaletteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v);
|
||||
VehicleSpriteSeq seq;
|
||||
@@ -3237,18 +3456,21 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
|
||||
if (rotor_seq) {
|
||||
GetCustomRotorSprite(Aircraft::From(v), image_type, &seq);
|
||||
if (!seq.IsValid()) seq.Set(SPR_ROTOR_STOPPED);
|
||||
y_offset = - ScaleGUITrad(5);
|
||||
y_offset = -ScaleSpriteTrad(5);
|
||||
} else {
|
||||
v->GetImage(rtl ? DIR_E : DIR_W, image_type, &seq);
|
||||
}
|
||||
|
||||
if (_cursor.sprite_count + seq.count > lengthof(_cursor.sprite_seq)) break;
|
||||
|
||||
int x_offs = 0;
|
||||
if (v->type == VEH_TRAIN) x_offs = Train::From(v)->GetCursorImageOffset();
|
||||
|
||||
for (uint i = 0; i < seq.count; ++i) {
|
||||
PaletteID pal2 = (v->vehstatus & VS_CRASHED) || !seq.seq[i].pal ? pal : seq.seq[i].pal;
|
||||
_cursor.sprite_seq[_cursor.sprite_count].sprite = seq.seq[i].sprite;
|
||||
_cursor.sprite_seq[_cursor.sprite_count].pal = pal2;
|
||||
_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? -total_width : total_width;
|
||||
_cursor.sprite_pos[_cursor.sprite_count].x = rtl ? (-total_width + x_offs) : (total_width + x_offs);
|
||||
_cursor.sprite_pos[_cursor.sprite_count].y = y_offset;
|
||||
_cursor.sprite_count++;
|
||||
}
|
||||
@@ -3264,7 +3486,7 @@ void SetMouseCursorVehicle(const Vehicle *v, EngineImageType image_type)
|
||||
|
||||
if (is_ground_vehicle) {
|
||||
/* Center trains and road vehicles on the front vehicle */
|
||||
int offs = (ScaleGUITrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2;
|
||||
int offs = (ScaleSpriteTrad(VEHICLEINFO_FULL_VEHICLE_WIDTH) - total_width) / 2;
|
||||
if (rtl) offs = -offs;
|
||||
for (uint i = 0; i < _cursor.sprite_count; ++i) {
|
||||
_cursor.sprite_pos[i].x += offs;
|
||||
|
||||
Reference in New Issue
Block a user