Show warning icon in order window if there are timetable warnings
This commit is contained in:
@@ -1677,6 +1677,17 @@ public:
|
||||
SetDParamMaxValue(0, 100);
|
||||
size->width = WD_FRAMERECT_LEFT + GetStringBoundingBox(STR_ORDERS_OCCUPANCY_PERCENT).width + 10 + WD_FRAMERECT_RIGHT;
|
||||
break;
|
||||
|
||||
case WID_O_TIMETABLE_VIEW: {
|
||||
Dimension d = GetStringBoundingBox(STR_ORDERS_TIMETABLE_VIEW);
|
||||
Dimension spr_d = GetSpriteSize(SPR_WARNING_SIGN);
|
||||
d.width += spr_d.width + 2;
|
||||
d.height = std::max(d.height, spr_d.height);
|
||||
d.width += padding.width;
|
||||
d.height += padding.height;
|
||||
*size = maxdim(*size, d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2034,6 +2045,10 @@ public:
|
||||
case WID_O_OCCUPANCY_LIST:
|
||||
DrawOccupancyListWidget(r);
|
||||
break;
|
||||
|
||||
case WID_O_TIMETABLE_VIEW:
|
||||
DrawTimetableButtonWidget(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2117,6 +2132,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTimetableButtonWidget(const Rect &r) const
|
||||
{
|
||||
const bool rtl = _current_text_dir == TD_RTL;
|
||||
bool clicked = this->GetWidget<NWidgetCore>(WID_O_TIMETABLE_VIEW)->IsLowered();
|
||||
Dimension d = GetStringBoundingBox(STR_ORDERS_TIMETABLE_VIEW);
|
||||
|
||||
int left = r.left + clicked;
|
||||
int right = r.right + clicked;
|
||||
|
||||
extern void ProcessTimetableWarnings(const Vehicle *v, std::function<void(StringID, bool)> handler);
|
||||
|
||||
bool show_warning = false;
|
||||
ProcessTimetableWarnings(this->vehicle, [&](StringID text, bool warning) {
|
||||
if (warning) show_warning = true;
|
||||
});
|
||||
|
||||
if (show_warning) {
|
||||
const Dimension warning_dimensions = GetSpriteSize(SPR_WARNING_SIGN);
|
||||
int spr_offset = std::max(0, ((int)(r.bottom - r.top + 1) - (int)warning_dimensions.height) / 2); // Offset for rendering the sprite vertically centered
|
||||
DrawSprite(SPR_WARNING_SIGN, 0, rtl ? right - warning_dimensions.width - 2 : left + 2, r.top + spr_offset);
|
||||
if (rtl) {
|
||||
right -= warning_dimensions.width;
|
||||
} else {
|
||||
left += warning_dimensions.width;
|
||||
}
|
||||
}
|
||||
int offset = std::max(0, ((int)(r.bottom - r.top + 1) - (int)d.height) / 2); // Offset for rendering the text vertically centered
|
||||
DrawString(left, right, r.top + offset + clicked, STR_ORDERS_TIMETABLE_VIEW, TC_FROMSTRING, SA_HOR_CENTER);
|
||||
}
|
||||
|
||||
void SetStringParameters(int widget) const override
|
||||
{
|
||||
switch (widget) {
|
||||
@@ -2819,7 +2864,7 @@ static const NWidgetPart _nested_orders_train_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(0x0, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
@@ -2935,7 +2980,7 @@ static const NWidgetPart _nested_orders_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(0x0, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
@@ -3036,7 +3081,7 @@ static const NWidgetPart _nested_other_orders_widgets[] = {
|
||||
NWidget(NWID_HORIZONTAL),
|
||||
NWidget(WWT_CLOSEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_CAPTION, COLOUR_GREY, WID_O_CAPTION), SetDataTip(STR_ORDERS_CAPTION, STR_TOOLTIP_WINDOW_TITLE_DRAG_THIS),
|
||||
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(STR_ORDERS_TIMETABLE_VIEW, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_PUSHBTN, COLOUR_GREY, WID_O_TIMETABLE_VIEW), SetMinimalSize(61, 14), SetDataTip(0x0, STR_ORDERS_TIMETABLE_VIEW_TOOLTIP),
|
||||
NWidget(WWT_SHADEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_DEFSIZEBOX, COLOUR_GREY),
|
||||
NWidget(WWT_STICKYBOX, COLOUR_GREY),
|
||||
|
@@ -173,6 +173,72 @@ static void ChangeTimetableStartCallback(const Window *w, DateTicksScaled date)
|
||||
ChangeTimetableStartIntl(w->window_number, date);
|
||||
}
|
||||
|
||||
void ProcessTimetableWarnings(const Vehicle *v, std::function<void(StringID, bool)> handler)
|
||||
{
|
||||
Ticks total_time = v->orders.list != nullptr ? v->orders.list->GetTimetableDurationIncomplete() : 0;
|
||||
|
||||
bool have_conditional = false;
|
||||
bool have_missing_wait = false;
|
||||
bool have_missing_travel = false;
|
||||
bool have_bad_full_load = false;
|
||||
bool have_non_timetabled_conditional_branch = false;
|
||||
|
||||
const bool assume_timetabled = HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE) || HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE);
|
||||
for (int n = 0; n < v->GetNumOrders(); n++) {
|
||||
const Order *order = v->GetOrder(n);
|
||||
if (order->IsType(OT_CONDITIONAL)) {
|
||||
have_conditional = true;
|
||||
if (!order->IsWaitTimetabled()) have_non_timetabled_conditional_branch = true;
|
||||
} else {
|
||||
if (order->GetWaitTime() == 0 && order->IsType(OT_GOTO_STATION) && !(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
|
||||
have_missing_wait = true;
|
||||
}
|
||||
if (order->GetTravelTime() == 0 && !order->IsTravelTimetabled()) {
|
||||
have_missing_travel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (order->IsType(OT_GOTO_STATION) && !have_bad_full_load && (assume_timetabled || order->IsWaitTimetabled())) {
|
||||
if (order->GetLoadType() & OLFB_FULL_LOAD) have_bad_full_load = true;
|
||||
if (order->GetLoadType() == OLFB_CARGO_TYPE_LOAD) {
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
if (order->GetCargoLoadTypeRaw(c) & OLFB_FULL_LOAD) {
|
||||
have_bad_full_load = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION)) {
|
||||
if (have_conditional) handler(STR_TIMETABLE_WARNING_AUTOSEP_CONDITIONAL, true);
|
||||
if (have_missing_wait || have_missing_travel) {
|
||||
if (assume_timetabled) {
|
||||
handler(STR_TIMETABLE_AUTOSEP_TIMETABLE_INCOMPLETE, false);
|
||||
} else {
|
||||
handler(STR_TIMETABLE_WARNING_AUTOSEP_MISSING_TIMINGS, true);
|
||||
}
|
||||
} else if (v->GetNumOrders() == 0) {
|
||||
handler(STR_TIMETABLE_AUTOSEP_TIMETABLE_INCOMPLETE, false);
|
||||
} else if (!have_conditional) {
|
||||
handler(v->IsOrderListShared() ? STR_TIMETABLE_AUTOSEP_OK : STR_TIMETABLE_AUTOSEP_SINGLE_VEH, false);
|
||||
}
|
||||
}
|
||||
if (have_bad_full_load) handler(STR_TIMETABLE_WARNING_FULL_LOAD, true);
|
||||
if (have_conditional && HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) handler(STR_TIMETABLE_WARNING_AUTOFILL_CONDITIONAL, true);
|
||||
if (total_time && have_non_timetabled_conditional_branch) handler(STR_TIMETABLE_NON_TIMETABLED_BRANCH, false);
|
||||
if (HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) {
|
||||
VehicleOrderID n = v->GetFirstWaitingLocation(false);
|
||||
if (n == INVALID_VEH_ORDER_ID) {
|
||||
handler(STR_TIMETABLE_WARNING_NO_SCHEDULED_DISPATCH_ORDER, true);
|
||||
} else if (!v->GetOrder(n)->IsWaitTimetabled()) {
|
||||
handler(STR_TIMETABLE_WARNING_SCHEDULED_DISPATCH_ORDER_NO_WAIT_TIME, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct TimetableWindow : Window {
|
||||
int sel_index;
|
||||
const Vehicle *vehicle; ///< Vehicle monitored by the window.
|
||||
@@ -608,40 +674,6 @@ struct TimetableWindow : Window {
|
||||
y += FONT_HEIGHT_NORMAL;
|
||||
|
||||
{
|
||||
bool have_conditional = false;
|
||||
bool have_missing_wait = false;
|
||||
bool have_missing_travel = false;
|
||||
bool have_bad_full_load = false;
|
||||
bool have_non_timetabled_conditional_branch = false;
|
||||
|
||||
const bool assume_timetabled = HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE) || HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE);
|
||||
for (int n = 0; n < v->GetNumOrders(); n++) {
|
||||
const Order *order = v->GetOrder(n);
|
||||
if (order->IsType(OT_CONDITIONAL)) {
|
||||
have_conditional = true;
|
||||
if (!order->IsWaitTimetabled()) have_non_timetabled_conditional_branch = true;
|
||||
} else {
|
||||
if (order->GetWaitTime() == 0 && order->IsType(OT_GOTO_STATION) && !(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
|
||||
have_missing_wait = true;
|
||||
}
|
||||
if (order->GetTravelTime() == 0 && !order->IsTravelTimetabled()) {
|
||||
have_missing_travel = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (order->IsType(OT_GOTO_STATION) && !have_bad_full_load && (assume_timetabled || order->IsWaitTimetabled())) {
|
||||
if (order->GetLoadType() & OLFB_FULL_LOAD) have_bad_full_load = true;
|
||||
if (order->GetLoadType() == OLFB_CARGO_TYPE_LOAD) {
|
||||
for (CargoID c = 0; c < NUM_CARGO; c++) {
|
||||
if (order->GetCargoLoadTypeRaw(c) & OLFB_FULL_LOAD) {
|
||||
have_bad_full_load = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Dimension warning_dimensions = GetSpriteSize(SPR_WARNING_SIGN);
|
||||
const int step_height = std::max<int>(warning_dimensions.height, FONT_HEIGHT_NORMAL);
|
||||
const int text_offset_y = (step_height - FONT_HEIGHT_NORMAL) / 2;
|
||||
@@ -650,7 +682,7 @@ struct TimetableWindow : Window {
|
||||
|
||||
int warning_count = 0;
|
||||
|
||||
auto draw_info = [&](StringID text, bool warning) {
|
||||
ProcessTimetableWarnings(v, [&](StringID text, bool warning) {
|
||||
int left = r.left + WD_FRAMERECT_LEFT;
|
||||
int right = r.right - WD_FRAMERECT_RIGHT;
|
||||
if (warning) {
|
||||
@@ -664,33 +696,7 @@ struct TimetableWindow : Window {
|
||||
DrawString(left, right, y + text_offset_y, text);
|
||||
y += step_height;
|
||||
warning_count++;
|
||||
};
|
||||
|
||||
if (HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION)) {
|
||||
if (have_conditional) draw_info(STR_TIMETABLE_WARNING_AUTOSEP_CONDITIONAL, true);
|
||||
if (have_missing_wait || have_missing_travel) {
|
||||
if (assume_timetabled) {
|
||||
draw_info(STR_TIMETABLE_AUTOSEP_TIMETABLE_INCOMPLETE, false);
|
||||
} else {
|
||||
draw_info(STR_TIMETABLE_WARNING_AUTOSEP_MISSING_TIMINGS, true);
|
||||
}
|
||||
} else if (v->GetNumOrders() == 0) {
|
||||
draw_info(STR_TIMETABLE_AUTOSEP_TIMETABLE_INCOMPLETE, false);
|
||||
} else if (!have_conditional) {
|
||||
draw_info(v->IsOrderListShared() ? STR_TIMETABLE_AUTOSEP_OK : STR_TIMETABLE_AUTOSEP_SINGLE_VEH, false);
|
||||
}
|
||||
}
|
||||
if (have_bad_full_load) draw_info(STR_TIMETABLE_WARNING_FULL_LOAD, true);
|
||||
if (have_conditional && HasBit(v->vehicle_flags, VF_AUTOFILL_TIMETABLE)) draw_info(STR_TIMETABLE_WARNING_AUTOFILL_CONDITIONAL, true);
|
||||
if (total_time && have_non_timetabled_conditional_branch) draw_info(STR_TIMETABLE_NON_TIMETABLED_BRANCH, false);
|
||||
if (HasBit(v->vehicle_flags, VF_SCHEDULED_DISPATCH)) {
|
||||
VehicleOrderID n = v->GetFirstWaitingLocation(false);
|
||||
if (n == INVALID_VEH_ORDER_ID) {
|
||||
draw_info(STR_TIMETABLE_WARNING_NO_SCHEDULED_DISPATCH_ORDER, true);
|
||||
} else if (!v->GetOrder(n)->IsWaitTimetabled()) {
|
||||
draw_info(STR_TIMETABLE_WARNING_SCHEDULED_DISPATCH_ORDER_NO_WAIT_TIME, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (warning_count != this->summary_warnings) {
|
||||
TimetableWindow *mutable_this = const_cast<TimetableWindow *>(this);
|
||||
|
Reference in New Issue
Block a user