Show warning icon in order window if there are timetable warnings

pull/217/head
Jonathan G Rennison 3 years ago
parent 2a0acd9d91
commit aa85ebe51e

@ -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);

Loading…
Cancel
Save