Changeset - r9258:00195392ad1f
[Not reviewed]
master
0 1 0
glx - 16 years ago 2008-05-16 20:08:20
glx@openttd.org
(svn r13124) -Codechange: make a class of the OrdersWindow.
1 file changed with 612 insertions and 648 deletions:
0 comments (0 inline, 0 general)
src/order_gui.cpp
Show inline comments
 
@@ -58,60 +58,6 @@ enum OrderWindowWidgets {
 
	ORDER_WIDGET_RESIZE,
 
};
 

	
 
/** Under what reason are we using the PlaceObject functionality? */
 
enum OrderPlaceObjectState {
 
	OPOS_GOTO,
 
	OPOS_CONDITIONAL,
 
};
 

	
 
struct order_d {
 
	int sel;
 
	OrderPlaceObjectState goto_type;
 
};
 
assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(order_d));
 

	
 
/**
 
 * Return the memorised selected order.
 
 *
 
 * @param w current window
 
 * @return the memorised order if it is a vaild one
 
 *  else return the number of orders
 
 */
 
static int OrderGetSel(const Window *w)
 
{
 
	const Vehicle *v = GetVehicle(w->window_number);
 
	int num = WP(w, order_d).sel;
 

	
 
	return (num >= 0 && num < v->num_orders) ? num : v->num_orders;
 
}
 

	
 
/**
 
 * Calculate the selected order.
 
 * The calculation is based on the relative (to the window) y click position and
 
 *  the position of the scrollbar.
 
 *
 
 * @param w current window
 
 * @param y Y-value of the click relative to the window origin
 
 * @param v current vehicle
 
 * @return the new selected order if the order is valid else return that
 
 *  an invalid one has been selected.
 
 */
 
static int GetOrderFromOrderWndPt(Window *w, int y, const Vehicle *v)
 
{
 
	/*
 
	 * Calculation description:
 
	 * 15 = 14 (w->widget[ORDER_WIDGET_ORDER_LIST].top) + 1 (frame-line)
 
	 * 10 = order text hight
 
	 */
 
	int sel = (y - w->widget[ORDER_WIDGET_ORDER_LIST].top - 1) / 10;
 

	
 
	if ((uint)sel >= w->vscroll.cap) return INVALID_ORDER;
 

	
 
	sel += w->vscroll.pos;
 

	
 
	return (sel <= v->num_orders && sel >= 0) ? sel : INVALID_ORDER;
 
}
 

	
 
/** Order load types that could be given to station orders. */
 
static const StringID _station_load_types[][5] = {
 
	{
 
@@ -312,121 +258,6 @@ void DrawOrderString(const Vehicle *v, c
 
}
 

	
 

	
 
static void DrawOrdersWindow(Window *w)
 
{
 
	const Vehicle *v = GetVehicle(w->window_number);
 
	bool shared_orders = v->IsOrderListShared();
 

	
 
	SetVScrollCount(w, v->num_orders + 1);
 

	
 
	int sel = OrderGetSel(w);
 
	const Order *order = GetVehicleOrder(v, sel);
 

	
 
	if (v->owner == _local_player) {
 
		/* Set the strings for the dropdown boxes. */
 
		w->widget[ORDER_WIDGET_NON_STOP].data        = _order_non_stop_drowdown[order == NULL ? 0 : order->GetNonStopType()];
 
		w->widget[ORDER_WIDGET_FULL_LOAD].data       = _order_full_load_drowdown[order == NULL ? 0 : order->GetLoadType()];
 
		w->widget[ORDER_WIDGET_UNLOAD].data          = _order_unload_drowdown[order == NULL ? 0 : order->GetUnloadType()];
 
		w->widget[ORDER_WIDGET_COND_VARIABLE].data   = _order_conditional_variable[order == NULL ? 0 : order->GetConditionVariable()];
 
		w->widget[ORDER_WIDGET_COND_COMPARATOR].data = _order_conditional_condition[order == NULL ? 0 : order->GetConditionComparator()];
 

	
 
		/* skip */
 
		w->SetWidgetDisabledState(ORDER_WIDGET_SKIP, v->num_orders <= 1);
 

	
 
		/* delete */
 
		w->SetWidgetDisabledState(ORDER_WIDGET_DELETE,
 
				(uint)v->num_orders + ((shared_orders || v->num_orders != 0) ? 1 : 0) <= (uint)WP(w, order_d).sel);
 

	
 
		/* non-stop only for trains */
 
		w->SetWidgetDisabledState(ORDER_WIDGET_NON_STOP,  (v->type != VEH_TRAIN && v->type != VEH_ROAD) || order == NULL);
 
		w->SetWidgetDisabledState(ORDER_WIDGET_FULL_LOAD, order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // full load
 
		w->SetWidgetDisabledState(ORDER_WIDGET_UNLOAD,    order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // unload
 
		/* Disable list of vehicles with the same shared orders if there is no list */
 
		w->SetWidgetDisabledState(ORDER_WIDGET_SHARED_ORDER_LIST, !shared_orders || v->orders == NULL);
 
		w->SetWidgetDisabledState(ORDER_WIDGET_REFIT,     order == NULL); // Refit
 
		w->SetWidgetDisabledState(ORDER_WIDGET_SERVICE,   order == NULL); // Refit
 
		w->HideWidget(ORDER_WIDGET_REFIT); // Refit
 
		w->HideWidget(ORDER_WIDGET_SERVICE); // Service
 

	
 
		w->HideWidget(ORDER_WIDGET_COND_VARIABLE);
 
		w->HideWidget(ORDER_WIDGET_COND_COMPARATOR);
 
		w->HideWidget(ORDER_WIDGET_COND_VALUE);
 
	}
 

	
 
	w->ShowWidget(ORDER_WIDGET_NON_STOP);
 
	w->ShowWidget(ORDER_WIDGET_UNLOAD);
 
	w->ShowWidget(ORDER_WIDGET_FULL_LOAD);
 

	
 
	if (order != NULL) {
 
		switch (order->GetType()) {
 
			case OT_GOTO_STATION:
 
				if (!GetStation(order->GetDestination())->IsBuoy()) break;
 
				/* Fall-through */
 

	
 
			case OT_GOTO_WAYPOINT:
 
				w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 
				w->DisableWidget(ORDER_WIDGET_UNLOAD);
 
				break;
 

	
 
			case OT_GOTO_DEPOT:
 
				w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 

	
 
				/* Remove unload and replace it with refit */
 
				w->HideWidget(ORDER_WIDGET_UNLOAD);
 
				w->ShowWidget(ORDER_WIDGET_REFIT);
 
				w->HideWidget(ORDER_WIDGET_FULL_LOAD);
 
				w->ShowWidget(ORDER_WIDGET_SERVICE);
 
				break;
 

	
 
			case OT_CONDITIONAL: {
 
				w->HideWidget(ORDER_WIDGET_NON_STOP);
 
				w->HideWidget(ORDER_WIDGET_UNLOAD);
 
				w->HideWidget(ORDER_WIDGET_FULL_LOAD);
 
				w->ShowWidget(ORDER_WIDGET_COND_VARIABLE);
 
				w->ShowWidget(ORDER_WIDGET_COND_COMPARATOR);
 
				w->ShowWidget(ORDER_WIDGET_COND_VALUE);
 

	
 
				OrderConditionVariable ocv = order->GetConditionVariable();
 
				w->SetWidgetDisabledState(ORDER_WIDGET_COND_COMPARATOR, ocv == OCV_UNCONDITIONALLY);
 
				w->SetWidgetDisabledState(ORDER_WIDGET_COND_VALUE, ocv == OCV_REQUIRES_SERVICE || ocv == OCV_UNCONDITIONALLY);
 

	
 
				uint value = order->GetConditionValue();
 
				if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
 
				SetDParam(1, value);
 
			} break;
 

	
 
			default: // every other orders
 
				w->DisableWidget(ORDER_WIDGET_NON_STOP);
 
				w->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 
				w->DisableWidget(ORDER_WIDGET_UNLOAD);
 
		}
 
	}
 

	
 
	SetDParam(0, v->index);
 
	DrawWindowWidgets(w);
 

	
 
	int y = 15;
 

	
 
	int i = w->vscroll.pos;
 
	order = GetVehicleOrder(v, i);
 
	StringID str;
 
	while (order != NULL) {
 
		/* Don't draw anything if it extends past the end of the window. */
 
		if (i - w->vscroll.pos >= w->vscroll.cap) break;
 

	
 
		DrawOrderString(v, order, i, y, i == WP(w, order_d).sel, false);
 
		y += 10;
 

	
 
		i++;
 
		order = order->next;
 
	}
 

	
 
	if (i - w->vscroll.pos < w->vscroll.cap) {
 
		str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
 
		DrawString(2, y, str, (i == WP(w, order_d).sel) ? TC_WHITE : TC_BLACK);
 
	}
 
}
 

	
 
static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
 
{
 
	Order order;
 
@@ -510,548 +341,689 @@ static Order GetOrderCmdFromTile(const V
 
	return order;
 
}
 

	
 
static bool HandleOrderVehClick(const Vehicle *v, const Vehicle *u, Window *w)
 
{
 
	if (u->type != v->type) return false;
 

	
 
	if (!u->IsPrimaryVehicle()) {
 
		u = u->First();
 
		if (!u->IsPrimaryVehicle()) return false;
 
	}
 
struct OrdersWindow : public Window {
 
private:
 
	/** Under what reason are we using the PlaceObject functionality? */
 
	enum OrderPlaceObjectState {
 
		OPOS_GOTO,
 
		OPOS_CONDITIONAL,
 
	};
 

	
 
	/* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
 
	 * obviously if you press CTRL on a non-empty orders vehicle you know what you are doing */
 
	if (v->num_orders != 0 && _ctrl_pressed == 0) return false;
 
	int selected_order;
 
	OrderPlaceObjectState goto_type;
 
	const Vehicle *vehicle;
 

	
 
	if (DoCommandP(v->tile, v->index | (u->index << 16), _ctrl_pressed ? CO_SHARE : CO_COPY, NULL,
 
		_ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_CANT_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_CANT_COPY_ORDER_LIST))) {
 
		WP(w, order_d).sel = -1;
 
		ResetObjectToPlace();
 
	/**
 
	 * Return the memorised selected order.
 
	 * @return the memorised order if it is a vaild one
 
	 *  else return the number of orders
 
	 */
 
	int OrderGetSel()
 
	{
 
		int num = this->selected_order;
 
		return (num >= 0 && num < vehicle->num_orders) ? num : vehicle->num_orders;
 
	}
 

	
 
	return true;
 
}
 

	
 
static void OrdersPlaceObj(const Vehicle *v, TileIndex tile, Window *w)
 
{
 
	/* check if we're clicking on a vehicle first.. clone orders in that case. */
 
	const Vehicle *u = CheckMouseOverVehicle();
 
	if (u != NULL && HandleOrderVehClick(v, u, w)) return;
 

	
 
	const Order cmd = GetOrderCmdFromTile(v, tile);
 
	if (!cmd.IsValid()) return;
 

	
 
	if (DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), cmd.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER))) {
 
		if (WP(w, order_d).sel != -1) WP(w, order_d).sel++;
 
		ResetObjectToPlace();
 
	}
 
}
 
	/**
 
	 * Calculate the selected order.
 
	 * The calculation is based on the relative (to the window) y click position and
 
	 *  the position of the scrollbar.
 
	 *
 
	 * @param y Y-value of the click relative to the window origin
 
	 * @param v current vehicle
 
	 * @return the new selected order if the order is valid else return that
 
	 *  an invalid one has been selected.
 
	 */
 
	int GetOrderFromPt(int y)
 
	{
 
		/*
 
		 * Calculation description:
 
		 * 15 = 14 (w->widget[ORDER_WIDGET_ORDER_LIST].top) + 1 (frame-line)
 
		 * 10 = order text hight
 
		 */
 
		int sel = (y - this->widget[ORDER_WIDGET_ORDER_LIST].top - 1) / 10;
 

	
 
/**
 
 * Handle the click on the goto button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Goto(Window *w, const Vehicle *v, int i)
 
{
 
	w->InvalidateWidget(ORDER_WIDGET_GOTO);
 
	w->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 
	if (w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
		_place_clicked_vehicle = NULL;
 
		SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
 
		WP(w, order_d).goto_type = OPOS_GOTO;
 
	} else {
 
		ResetObjectToPlace();
 
	}
 
}
 
		if ((uint)sel >= this->vscroll.cap) return INVALID_ORDER;
 

	
 
		sel += this->vscroll.pos;
 

	
 
/**
 
 * Handle the click on the full load button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 * @param load_type the way to load.
 
 */
 
static void OrderClick_FullLoad(Window *w, const Vehicle *v, int load_type)
 
{
 
	VehicleOrderID sel_ord = OrderGetSel(w);
 
	const Order *order = GetVehicleOrder(v, sel_ord);
 
		return (sel <= vehicle->num_orders && sel >= 0) ? sel : INVALID_ORDER;
 
	}
 

	
 
	if (order->GetLoadType() == load_type) return;
 

	
 
	if (load_type < 0) {
 
		switch (order->GetLoadType()) {
 
			case OLF_LOAD_IF_POSSIBLE: load_type = OLFB_FULL_LOAD;       break;
 
			case OLFB_FULL_LOAD:       load_type = OLF_FULL_LOAD_ANY;    break;
 
			case OLF_FULL_LOAD_ANY:    load_type = OLFB_NO_LOAD;         break;
 
			case OLFB_NO_LOAD:         load_type = OLF_LOAD_IF_POSSIBLE; break;
 
			default: NOT_REACHED();
 
		}
 
	}
 
	DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_LOAD | (load_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
}
 
	bool HandleOrderVehClick(const Vehicle *u)
 
	{
 
		if (u->type != this->vehicle->type) return false;
 

	
 
/**
 
 * Handle the click on the service.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Service(Window *w, const Vehicle *v, int i)
 
{
 
	DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), MOF_DEPOT_ACTION, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
}
 
		if (!u->IsPrimaryVehicle()) {
 
			u = u->First();
 
			if (!u->IsPrimaryVehicle()) return false;
 
		}
 

	
 
/**
 
 * Handle the click on the service in nearest depot button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_NearestDepot(Window *w, const Vehicle *v, int i)
 
{
 
	Order order;
 
	order.next = NULL;
 
	order.index = 0;
 
	order.MakeGoToDepot(0, ODTFB_PART_OF_ORDERS);
 
	order.SetDepotActionType(ODATFB_NEAREST_DEPOT);
 
		/* v is vehicle getting orders. Only copy/clone orders if vehicle doesn't have any orders yet
 
		 * obviously if you press CTRL on a non-empty orders vehicle you know what you are doing */
 
		if (this->vehicle->num_orders != 0 && _ctrl_pressed == 0) return false;
 

	
 
	DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
 
}
 
		if (DoCommandP(this->vehicle->tile, this->vehicle->index | (u->index << 16), _ctrl_pressed ? CO_SHARE : CO_COPY, NULL,
 
			_ctrl_pressed ? CMD_CLONE_ORDER | CMD_MSG(STR_CANT_SHARE_ORDER_LIST) : CMD_CLONE_ORDER | CMD_MSG(STR_CANT_COPY_ORDER_LIST))) {
 
			this->selected_order = -1;
 
			ResetObjectToPlace();
 
		}
 

	
 
/**
 
 * Handle the click on the conditional order button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Conditional(Window *w, const Vehicle *v, int i)
 
{
 
	w->InvalidateWidget(ORDER_WIDGET_GOTO);
 
	w->LowerWidget(ORDER_WIDGET_GOTO);
 
	SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
 
	WP(w, order_d).goto_type = OPOS_CONDITIONAL;
 
}
 
		return true;
 
	}
 

	
 
/**
 
 * Handle the click on the unload button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Unload(Window *w, const Vehicle *v, int unload_type)
 
{
 
	VehicleOrderID sel_ord = OrderGetSel(w);
 
	const Order *order = GetVehicleOrder(v, sel_ord);
 

	
 
	if (order->GetUnloadType() == unload_type) return;
 

	
 
	if (unload_type < 0) {
 
		switch (order->GetUnloadType()) {
 
			case OUF_UNLOAD_IF_POSSIBLE: unload_type = OUFB_UNLOAD;            break;
 
			case OUFB_UNLOAD:            unload_type = OUFB_TRANSFER;          break;
 
			case OUFB_TRANSFER:          unload_type = OUFB_NO_UNLOAD;         break;
 
			case OUFB_NO_UNLOAD:         unload_type = OUF_UNLOAD_IF_POSSIBLE; break;
 
			default: NOT_REACHED();
 
	/**
 
	 * Handle the click on the goto button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Goto(OrdersWindow *w, int i)
 
	{
 
		w->InvalidateWidget(ORDER_WIDGET_GOTO);
 
		w->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 
		if (w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
			_place_clicked_vehicle = NULL;
 
			SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
 
			w->goto_type = OPOS_GOTO;
 
		} else {
 
			ResetObjectToPlace();
 
		}
 
	}
 

	
 
	DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | (unload_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
}
 
	/**
 
	 * Handle the click on the full load button.
 
	 *
 
	 * @param w current window
 
	 * @param load_type the way to load.
 
	 */
 
	static void OrderClick_FullLoad(OrdersWindow *w, int load_type)
 
	{
 
		VehicleOrderID sel_ord = w->OrderGetSel();
 
		const Order *order = GetVehicleOrder(w->vehicle, sel_ord);
 

	
 
		if (order == NULL || order->GetLoadType() == load_type) return;
 

	
 
		if (load_type < 0) {
 
			switch (order->GetLoadType()) {
 
				case OLF_LOAD_IF_POSSIBLE: load_type = OLFB_FULL_LOAD;       break;
 
				case OLFB_FULL_LOAD:       load_type = OLF_FULL_LOAD_ANY;    break;
 
				case OLF_FULL_LOAD_ANY:    load_type = OLFB_NO_LOAD;         break;
 
				case OLFB_NO_LOAD:         load_type = OLF_LOAD_IF_POSSIBLE; break;
 
				default: NOT_REACHED();
 
			}
 
		}
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (sel_ord << 16), MOF_LOAD | (load_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the service.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Service(OrdersWindow *w, int i)
 
	{
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (w->OrderGetSel() << 16), MOF_DEPOT_ACTION, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the service in nearest depot button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_NearestDepot(OrdersWindow *w, int i)
 
	{
 
		Order order;
 
		order.next = NULL;
 
		order.index = 0;
 
		order.MakeGoToDepot(0, ODTFB_PART_OF_ORDERS);
 
		order.SetDepotActionType(ODATFB_NEAREST_DEPOT);
 

	
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (w->OrderGetSel() << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
 
	}
 

	
 
/**
 
 * Handle the click on the nonstop button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 * @param non_stop what non-stop type to use; -1 to use the 'next' one.
 
 */
 
static void OrderClick_Nonstop(Window *w, const Vehicle *v, int non_stop)
 
{
 
	VehicleOrderID sel_ord = OrderGetSel(w);
 
	const Order *order = GetVehicleOrder(v, sel_ord);
 
	/**
 
	 * Handle the click on the conditional order button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Conditional(OrdersWindow *w, int i)
 
	{
 
		w->InvalidateWidget(ORDER_WIDGET_GOTO);
 
		w->LowerWidget(ORDER_WIDGET_GOTO);
 
		SetObjectToPlaceWnd(ANIMCURSOR_PICKSTATION, PAL_NONE, VHM_RECT, w);
 
		w->goto_type = OPOS_CONDITIONAL;
 
	}
 

	
 
	/**
 
	 * Handle the click on the unload button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Unload(OrdersWindow *w, int unload_type)
 
	{
 
		VehicleOrderID sel_ord = w->OrderGetSel();
 
		const Order *order = GetVehicleOrder(w->vehicle, sel_ord);
 

	
 
		if (order == NULL || order->GetUnloadType() == unload_type) return;
 

	
 
		if (unload_type < 0) {
 
			switch (order->GetUnloadType()) {
 
				case OUF_UNLOAD_IF_POSSIBLE: unload_type = OUFB_UNLOAD;            break;
 
				case OUFB_UNLOAD:            unload_type = OUFB_TRANSFER;          break;
 
				case OUFB_TRANSFER:          unload_type = OUFB_NO_UNLOAD;         break;
 
				case OUFB_NO_UNLOAD:         unload_type = OUF_UNLOAD_IF_POSSIBLE; break;
 
				default: NOT_REACHED();
 
			}
 
		}
 

	
 
	if (order->GetNonStopType() == non_stop) return;
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (sel_ord << 16), MOF_UNLOAD | (unload_type << 4), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the nonstop button.
 
	 *
 
	 * @param w current window
 
	 * @param non_stop what non-stop type to use; -1 to use the 'next' one.
 
	 */
 
	static void OrderClick_Nonstop(OrdersWindow *w, int non_stop)
 
	{
 
		VehicleOrderID sel_ord = w->OrderGetSel();
 
		const Order *order = GetVehicleOrder(w->vehicle, sel_ord);
 

	
 
		if (order == NULL || order->GetNonStopType() == non_stop) return;
 

	
 
	/* Keypress if negative, so 'toggle' to the next */
 
	if (non_stop < 0) {
 
		non_stop = (order->GetNonStopType() + 1) % ONSF_END;
 
		/* Keypress if negative, so 'toggle' to the next */
 
		if (non_stop < 0) {
 
			non_stop = (order->GetNonStopType() + 1) % ONSF_END;
 
		}
 

	
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (sel_ord << 16), MOF_NON_STOP | non_stop << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	/**
 
	 * Handle the click on the transfer button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Transfer(OrdersWindow *w, int i)
 
	{
 
		VehicleOrderID sel_ord = w->OrderGetSel();
 
		const Order *order = GetVehicleOrder(w->vehicle, sel_ord);
 

	
 
		if (order == NULL) return;
 

	
 
		DoCommandP(w->vehicle->tile, w->vehicle->index + (sel_ord << 16), MOF_UNLOAD | ((order->GetUnloadType() & ~OUFB_NO_UNLOAD) ^ OUFB_TRANSFER) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
	}
 

	
 
	DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_NON_STOP | non_stop << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
}
 

	
 
/**
 
 * Handle the click on the transfer button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Transfer(Window *w, const Vehicle *v, int i)
 
{
 
	VehicleOrderID sel_ord = OrderGetSel(w);
 
	const Order *order = GetVehicleOrder(v, sel_ord);
 
	/**
 
	 * Handle the click on the skip button.
 
	 * If ctrl is pressed skip to selected order.
 
	 *  Else skip to current order + 1
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Skip(OrdersWindow *w, int i)
 
	{
 
		/* Don't skip when there's nothing to skip */
 
		if (_ctrl_pressed && w->vehicle->cur_order_index == w->OrderGetSel()) return;
 

	
 
	DoCommandP(v->tile, v->index + (sel_ord << 16), MOF_UNLOAD | ((order->GetUnloadType() & ~OUFB_NO_UNLOAD) ^ OUFB_TRANSFER) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
}
 

	
 
/**
 
 * Handle the click on the skip button.
 
 * If ctrl is pressed skip to selected order.
 
 *  Else skip to current order + 1
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Skip(Window *w, const Vehicle *v, int i)
 
{
 
	/* Don't skip when there's nothing to skip */
 
	if (_ctrl_pressed && v->cur_order_index == OrderGetSel(w)) return;
 
		DoCommandP(w->vehicle->tile, w->vehicle->index, _ctrl_pressed ? w->OrderGetSel() : ((w->vehicle->cur_order_index + 1) % w->vehicle->num_orders),
 
				NULL, CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_CAN_T_SKIP_TO_ORDER : STR_CAN_T_SKIP_ORDER));
 
	}
 

	
 
	DoCommandP(v->tile, v->index, _ctrl_pressed ? OrderGetSel(w) : ((v->cur_order_index + 1) % v->num_orders),
 
			NULL, CMD_SKIP_TO_ORDER | CMD_MSG(_ctrl_pressed ? STR_CAN_T_SKIP_TO_ORDER : STR_CAN_T_SKIP_ORDER));
 
}
 

	
 
/**
 
 * Handle the click on the unload button.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Delete(Window *w, const Vehicle *v, int i)
 
{
 
	DoCommandP(v->tile, v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
 
}
 
	/**
 
	 * Handle the click on the unload button.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Delete(OrdersWindow *w, int i)
 
	{
 
		DoCommandP(w->vehicle->tile, w->vehicle->index, w->OrderGetSel(), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
 
	}
 

	
 
/**
 
 * Handle the click on the refit button.
 
 * If ctrl is pressed cancel refitting.
 
 *  Else show the refit window.
 
 *
 
 * @param w current window
 
 * @param v current vehicle
 
 */
 
static void OrderClick_Refit(Window *w, const Vehicle *v, int i)
 
{
 
	if (_ctrl_pressed) {
 
		/* Cancel refitting */
 
		DoCommandP(v->tile, v->index, (WP(w, order_d).sel << 16) | (CT_NO_REFIT << 8) | CT_NO_REFIT, NULL, CMD_ORDER_REFIT);
 
	} else {
 
		ShowVehicleRefitWindow(v, WP(w, order_d).sel);
 
	/**
 
	 * Handle the click on the refit button.
 
	 * If ctrl is pressed cancel refitting.
 
	 *  Else show the refit window.
 
	 *
 
	 * @param w current window
 
	 */
 
	static void OrderClick_Refit(OrdersWindow *w, int i)
 
	{
 
		if (_ctrl_pressed) {
 
			/* Cancel refitting */
 
			DoCommandP(w->vehicle->tile, w->vehicle->index, (w->OrderGetSel() << 16) | (CT_NO_REFIT << 8) | CT_NO_REFIT, NULL, CMD_ORDER_REFIT);
 
		} else {
 
			ShowVehicleRefitWindow(w->vehicle, w->OrderGetSel());
 
		}
 
	}
 
}
 

	
 
typedef void OnButtonVehClick(Window *w, const Vehicle *v, int i);
 
	typedef void Handler(OrdersWindow*, int);
 
	struct KeyToEvent {
 
		uint16 keycode;
 
		Handler *proc;
 
	};
 

	
 
/**
 
 * Keycode function mapping.
 
 *
 
 * @see _order_keycodes[]
 
 * @note Keep them allways in sync with _order_keycodes[]!
 
 */
 
static OnButtonVehClick* const _order_button_proc[] = {
 
	OrderClick_Skip,
 
	OrderClick_Delete,
 
	OrderClick_Nonstop,
 
	OrderClick_Goto,
 
	OrderClick_FullLoad,
 
	OrderClick_Unload,
 
	OrderClick_Transfer,
 
	OrderClick_Service,
 
};
 
public:
 
	OrdersWindow(const WindowDesc *desc, const Vehicle *v) : Window(desc, v->index)
 
	{
 
		this->caption_color = v->owner;
 
		this->vscroll.cap = 6;
 
		this->resize.step_height = 10;
 
		this->selected_order = -1;
 
		this->vehicle = v;
 
		if (_patches.timetabling) {
 
			this->widget[ORDER_WIDGET_CAPTION].right -= 61;
 
		} else {
 
			this->HideWidget(ORDER_WIDGET_TIMETABLE_VIEW);
 
		}
 
		this->FindWindowPlacementAndResize(desc);
 
	}
 

	
 
static const uint16 _order_keycodes[] = {
 
	'D', //skip order
 
	'F', //delete order
 
	'G', //non-stop
 
	'H', //goto order
 
	'J', //full load
 
	'K'  //unload
 
};
 
	virtual void OnPaint()
 
	{
 
		bool shared_orders = this->vehicle->IsOrderListShared();
 

	
 
static void OrdersWndProc(Window *w, WindowEvent *e)
 
{
 
	const Vehicle *v = GetVehicle(w->window_number);
 
		SetVScrollCount(this, this->vehicle->num_orders + 1);
 

	
 
	switch (e->event) {
 
		case WE_CREATE:
 
			if (_patches.timetabling) {
 
				w->widget[ORDER_WIDGET_CAPTION].right -= 61;
 
			} else {
 
				w->HideWidget(ORDER_WIDGET_TIMETABLE_VIEW);
 
			}
 
		int sel = OrderGetSel();
 
		const Order *order = GetVehicleOrder(this->vehicle, sel);
 

	
 
			break;
 

	
 
		case WE_PAINT:
 
			DrawOrdersWindow(w);
 
			break;
 
		if (this->vehicle->owner == _local_player) {
 
			/* Set the strings for the dropdown boxes. */
 
			this->widget[ORDER_WIDGET_NON_STOP].data        = _order_non_stop_drowdown[order == NULL ? 0 : order->GetNonStopType()];
 
			this->widget[ORDER_WIDGET_FULL_LOAD].data       = _order_full_load_drowdown[order == NULL ? 0 : order->GetLoadType()];
 
			this->widget[ORDER_WIDGET_UNLOAD].data          = _order_unload_drowdown[order == NULL ? 0 : order->GetUnloadType()];
 
			this->widget[ORDER_WIDGET_COND_VARIABLE].data   = _order_conditional_variable[order == NULL ? 0 : order->GetConditionVariable()];
 
			this->widget[ORDER_WIDGET_COND_COMPARATOR].data = _order_conditional_condition[order == NULL ? 0 : order->GetConditionComparator()];
 

	
 
		case WE_CLICK:
 
			if (w->widget[e->we.click.widget].type != WWT_DROPDOWN) HideDropDownMenu(w);
 
			switch (e->we.click.widget) {
 
				case ORDER_WIDGET_ORDER_LIST: {
 
					ResetObjectToPlace();
 
			/* skip */
 
			this->SetWidgetDisabledState(ORDER_WIDGET_SKIP, this->vehicle->num_orders <= 1);
 

	
 
					int sel = GetOrderFromOrderWndPt(w, e->we.click.pt.y, v);
 
			/* delete */
 
			this->SetWidgetDisabledState(ORDER_WIDGET_DELETE,
 
					(uint)this->vehicle->num_orders + ((shared_orders || this->vehicle->num_orders != 0) ? 1 : 0) <= (uint)this->selected_order);
 

	
 
					if (sel == INVALID_ORDER) {
 
						/* This was a click on an empty part of the orders window, so
 
						* deselect the currently selected order. */
 
						WP(w, order_d).sel = -1;
 
						w->SetDirty();
 
						return;
 
					}
 

	
 
					if (_ctrl_pressed && sel < v->num_orders) {
 
						const Order *ord = GetVehicleOrder(v, sel);
 
						TileIndex xy;
 
			/* non-stop only for trains */
 
			this->SetWidgetDisabledState(ORDER_WIDGET_NON_STOP,  (this->vehicle->type != VEH_TRAIN && this->vehicle->type != VEH_ROAD) || order == NULL);
 
			this->SetWidgetDisabledState(ORDER_WIDGET_FULL_LOAD, order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // full load
 
			this->SetWidgetDisabledState(ORDER_WIDGET_UNLOAD,    order == NULL || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0); // unload
 
			/* Disable list of vehicles with the same shared orders if there is no list */
 
			this->SetWidgetDisabledState(ORDER_WIDGET_SHARED_ORDER_LIST, !shared_orders || this->vehicle->orders == NULL);
 
			this->SetWidgetDisabledState(ORDER_WIDGET_REFIT,     order == NULL); // Refit
 
			this->SetWidgetDisabledState(ORDER_WIDGET_SERVICE,   order == NULL); // Refit
 
			this->HideWidget(ORDER_WIDGET_REFIT); // Refit
 
			this->HideWidget(ORDER_WIDGET_SERVICE); // Service
 

	
 
						switch (ord->GetType()) {
 
							case OT_GOTO_STATION:  xy = GetStation(ord->GetDestination())->xy ; break;
 
							case OT_GOTO_DEPOT:    xy = (v->type == VEH_AIRCRAFT) ?  GetStation(ord->GetDestination())->xy : GetDepot(ord->GetDestination())->xy;    break;
 
							case OT_GOTO_WAYPOINT: xy = GetWaypoint(ord->GetDestination())->xy; break;
 
							default:               xy = 0; break;
 
						}
 
			this->HideWidget(ORDER_WIDGET_COND_VARIABLE);
 
			this->HideWidget(ORDER_WIDGET_COND_COMPARATOR);
 
			this->HideWidget(ORDER_WIDGET_COND_VALUE);
 
		}
 

	
 
		this->ShowWidget(ORDER_WIDGET_NON_STOP);
 
		this->ShowWidget(ORDER_WIDGET_UNLOAD);
 
		this->ShowWidget(ORDER_WIDGET_FULL_LOAD);
 

	
 
						if (xy != 0) ScrollMainWindowToTile(xy);
 
						return;
 
					} else {
 
						if (sel == WP(w, order_d).sel) {
 
							/* Deselect clicked order */
 
							WP(w, order_d).sel = -1;
 
						} else {
 
							/* Select clicked order */
 
							WP(w, order_d).sel = sel;
 
		if (order != NULL) {
 
			switch (order->GetType()) {
 
				case OT_GOTO_STATION:
 
					if (!GetStation(order->GetDestination())->IsBuoy()) break;
 
					/* Fall-through */
 

	
 
							if (v->owner == _local_player) {
 
								/* Activate drag and drop */
 
								SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, VHM_DRAG, w);
 
							}
 
						}
 
					}
 

	
 
					w->SetDirty();
 
				} break;
 

	
 
				case ORDER_WIDGET_SKIP:
 
					OrderClick_Skip(w, v, 0);
 
				case OT_GOTO_WAYPOINT:
 
					this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 
					this->DisableWidget(ORDER_WIDGET_UNLOAD);
 
					break;
 

	
 
				case ORDER_WIDGET_DELETE:
 
					OrderClick_Delete(w, v, 0);
 
					break;
 
				case OT_GOTO_DEPOT:
 
					this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 

	
 
				case ORDER_WIDGET_NON_STOP: {
 
					const Order *o = GetVehicleOrder(v, OrderGetSel(w));
 
					ShowDropDownMenu(w, _order_non_stop_drowdown, o->GetNonStopType(), ORDER_WIDGET_NON_STOP, 0, o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
 
				} break;
 

	
 
				case ORDER_WIDGET_GOTO:
 
					OrderClick_Goto(w, v, 0);
 
					/* Remove unload and replace it with refit */
 
					this->HideWidget(ORDER_WIDGET_UNLOAD);
 
					this->ShowWidget(ORDER_WIDGET_REFIT);
 
					this->HideWidget(ORDER_WIDGET_FULL_LOAD);
 
					this->ShowWidget(ORDER_WIDGET_SERVICE);
 
					break;
 

	
 
				case ORDER_WIDGET_GOTO_DROPDOWN:
 
					ShowDropDownMenu(w, v->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, 0, ORDER_WIDGET_GOTO, 0, 0, w->widget[ORDER_WIDGET_GOTO_DROPDOWN].right - w->widget[ORDER_WIDGET_GOTO].left);
 
					break;
 

	
 
				case ORDER_WIDGET_FULL_LOAD:
 
					ShowDropDownMenu(w, _order_full_load_drowdown, GetVehicleOrder(v, OrderGetSel(w))->GetLoadType(), ORDER_WIDGET_FULL_LOAD, 0, 2);
 
					break;
 

	
 
				case ORDER_WIDGET_UNLOAD:
 
					ShowDropDownMenu(w, _order_unload_drowdown, GetVehicleOrder(v, OrderGetSel(w))->GetUnloadType(), ORDER_WIDGET_UNLOAD, 0, 8);
 
					break;
 

	
 
				case ORDER_WIDGET_REFIT:
 
					OrderClick_Refit(w, v, 0);
 
					break;
 
				case OT_CONDITIONAL: {
 
					this->HideWidget(ORDER_WIDGET_NON_STOP);
 
					this->HideWidget(ORDER_WIDGET_UNLOAD);
 
					this->HideWidget(ORDER_WIDGET_FULL_LOAD);
 
					this->ShowWidget(ORDER_WIDGET_COND_VARIABLE);
 
					this->ShowWidget(ORDER_WIDGET_COND_COMPARATOR);
 
					this->ShowWidget(ORDER_WIDGET_COND_VALUE);
 

	
 
				case ORDER_WIDGET_SERVICE:
 
					OrderClick_Service(w, v, 0);
 
					break;
 

	
 
				case ORDER_WIDGET_TIMETABLE_VIEW:
 
					ShowTimetableWindow(v);
 
					break;
 
					OrderConditionVariable ocv = order->GetConditionVariable();
 
					this->SetWidgetDisabledState(ORDER_WIDGET_COND_COMPARATOR, ocv == OCV_UNCONDITIONALLY);
 
					this->SetWidgetDisabledState(ORDER_WIDGET_COND_VALUE, ocv == OCV_REQUIRES_SERVICE || ocv == OCV_UNCONDITIONALLY);
 

	
 
				case ORDER_WIDGET_COND_VARIABLE:
 
					ShowDropDownMenu(w, _order_conditional_variable, GetVehicleOrder(v, OrderGetSel(w))->GetConditionVariable(), ORDER_WIDGET_COND_VARIABLE, 0, 0);
 
					break;
 

	
 
				case ORDER_WIDGET_COND_COMPARATOR: {
 
					const Order *o = GetVehicleOrder(v, OrderGetSel(w));
 
					ShowDropDownMenu(w, _order_conditional_condition, o->GetConditionComparator(), ORDER_WIDGET_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
 
				} break;
 

	
 
				case ORDER_WIDGET_COND_VALUE: {
 
					const Order *order = GetVehicleOrder(v, OrderGetSel(w));
 
					uint value = order->GetConditionValue();
 
					if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
 
					SetDParam(0, value);
 
					ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, 100, w, CS_NUMERAL);
 
					SetDParam(1, value);
 
				} break;
 

	
 
				case ORDER_WIDGET_SHARED_ORDER_LIST:
 
					ShowVehicleListWindow(v);
 
					break;
 
				default: // every other orders
 
					this->DisableWidget(ORDER_WIDGET_NON_STOP);
 
					this->DisableWidget(ORDER_WIDGET_FULL_LOAD);
 
					this->DisableWidget(ORDER_WIDGET_UNLOAD);
 
			}
 
			break;
 
		}
 

	
 
		SetDParam(0, this->vehicle->index);
 
		DrawWindowWidgets(this);
 

	
 
		int y = 15;
 

	
 
		case WE_ON_EDIT_TEXT:
 
			if (!StrEmpty(e->we.edittext.str)) {
 
				VehicleOrderID sel = OrderGetSel(w);
 
				uint value = atoi(e->we.edittext.str);
 
		int i = this->vscroll.pos;
 
		order = GetVehicleOrder(this->vehicle, i);
 
		StringID str;
 
		while (order != NULL) {
 
			/* Don't draw anything if it extends past the end of the window. */
 
			if (i - this->vscroll.pos >= this->vscroll.cap) break;
 

	
 
			DrawOrderString(this->vehicle, order, i, y, i == this->selected_order, false);
 
			y += 10;
 

	
 
			i++;
 
			order = order->next;
 
		}
 

	
 
		if (i - this->vscroll.pos < this->vscroll.cap) {
 
			str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
 
			DrawString(2, y, str, (i == this->selected_order) ? TC_WHITE : TC_BLACK);
 
		}
 
	}
 

	
 
				switch (GetVehicleOrder(v, sel)->GetConditionVariable()) {
 
					case OCV_MAX_SPEED:
 
						value = ConvertDisplaySpeedToSpeed(value);
 
						break;
 
	virtual void OnClick(Point pt, int widget)
 
	{
 
		if (this->widget[widget].type != WWT_DROPDOWN) HideDropDownMenu(this);
 
		switch (widget) {
 
			case ORDER_WIDGET_ORDER_LIST: {
 
				ResetObjectToPlace();
 

	
 
				int sel = this->GetOrderFromPt(pt.y);
 

	
 
				if (sel == INVALID_ORDER) {
 
					/* This was a click on an empty part of the orders window, so
 
					* deselect the currently selected order. */
 
					this->selected_order = -1;
 
					this->SetDirty();
 
					return;
 
				}
 

	
 
				if (_ctrl_pressed && sel < this->vehicle->num_orders) {
 
					const Order *ord = GetVehicleOrder(this->vehicle, sel);
 
					TileIndex xy;
 

	
 
					case OCV_RELIABILITY:
 
					case OCV_LOAD_PERCENTAGE:
 
						value = Clamp(value, 0, 100);
 
					switch (ord->GetType()) {
 
						case OT_GOTO_STATION:  xy = GetStation(ord->GetDestination())->xy ; break;
 
						case OT_GOTO_DEPOT:    xy = (this->vehicle->type == VEH_AIRCRAFT) ?  GetStation(ord->GetDestination())->xy : GetDepot(ord->GetDestination())->xy;    break;
 
						case OT_GOTO_WAYPOINT: xy = GetWaypoint(ord->GetDestination())->xy; break;
 
						default:               xy = 0; break;
 
					}
 

	
 
					default:
 
						break;
 
					if (xy != 0) ScrollMainWindowToTile(xy);
 
					return;
 
				} else {
 
					if (sel == this->selected_order) {
 
						/* Deselect clicked order */
 
						this->selected_order = -1;
 
					} else {
 
						/* Select clicked order */
 
						this->selected_order = sel;
 

	
 
						if (this->vehicle->owner == _local_player) {
 
							/* Activate drag and drop */
 
							SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, VHM_DRAG, this);
 
						}
 
					}
 
				}
 
				DoCommandP(v->tile, v->index + (sel << 16), MOF_COND_VALUE | Clamp(value, 0, 2047) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
			}
 
			break;
 

	
 
		case WE_DROPDOWN_SELECT: // we have selected a dropdown item in the list
 
			switch (e->we.dropdown.button) {
 
				case ORDER_WIDGET_NON_STOP:
 
					OrderClick_Nonstop(w, v, e->we.dropdown.index);
 
					break;
 
				this->SetDirty();
 
			} break;
 

	
 
			case ORDER_WIDGET_SKIP:
 
				OrderClick_Skip(this, 0);
 
				break;
 

	
 
			case ORDER_WIDGET_DELETE:
 
				OrderClick_Delete(this, 0);
 
				break;
 

	
 
			case ORDER_WIDGET_NON_STOP: {
 
				const Order *o = GetVehicleOrder(this->vehicle, this->OrderGetSel());
 
				ShowDropDownMenu(this, _order_non_stop_drowdown, o->GetNonStopType(), ORDER_WIDGET_NON_STOP, 0, o->IsType(OT_GOTO_STATION) ? 0 : (o->IsType(OT_GOTO_WAYPOINT) ? 3 : 12));
 
			} break;
 

	
 
				case ORDER_WIDGET_FULL_LOAD:
 
					OrderClick_FullLoad(w, v, e->we.dropdown.index);
 
					break;
 
			case ORDER_WIDGET_GOTO:
 
				OrderClick_Goto(this, 0);
 
				break;
 

	
 
			case ORDER_WIDGET_GOTO_DROPDOWN:
 
				ShowDropDownMenu(this, this->vehicle->type == VEH_AIRCRAFT ? _order_goto_dropdown_aircraft : _order_goto_dropdown, 0, ORDER_WIDGET_GOTO, 0, 0, this->widget[ORDER_WIDGET_GOTO_DROPDOWN].right - this->widget[ORDER_WIDGET_GOTO].left);
 
				break;
 

	
 
				case ORDER_WIDGET_UNLOAD:
 
					OrderClick_Unload(w, v, e->we.dropdown.index);
 
					break;
 
			case ORDER_WIDGET_FULL_LOAD:
 
				ShowDropDownMenu(this, _order_full_load_drowdown, GetVehicleOrder(this->vehicle, this->OrderGetSel())->GetLoadType(), ORDER_WIDGET_FULL_LOAD, 0, 2);
 
				break;
 

	
 
			case ORDER_WIDGET_UNLOAD:
 
				ShowDropDownMenu(this, _order_unload_drowdown, GetVehicleOrder(this->vehicle, this->OrderGetSel())->GetUnloadType(), ORDER_WIDGET_UNLOAD, 0, 8);
 
				break;
 

	
 
			case ORDER_WIDGET_REFIT:
 
				OrderClick_Refit(this, 0);
 
				break;
 

	
 
				case ORDER_WIDGET_GOTO:
 
					switch (e->we.dropdown.index) {
 
						case 0:
 
							w->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 
							OrderClick_Goto(w, v, 0);
 
							break;
 
			case ORDER_WIDGET_SERVICE:
 
				OrderClick_Service(this, 0);
 
				break;
 

	
 
			case ORDER_WIDGET_TIMETABLE_VIEW:
 
				ShowTimetableWindow(this->vehicle);
 
				break;
 

	
 
			case ORDER_WIDGET_COND_VARIABLE:
 
				ShowDropDownMenu(this, _order_conditional_variable, GetVehicleOrder(this->vehicle, this->OrderGetSel())->GetConditionVariable(), ORDER_WIDGET_COND_VARIABLE, 0, 0);
 
				break;
 

	
 
			case ORDER_WIDGET_COND_COMPARATOR: {
 
				const Order *o = GetVehicleOrder(this->vehicle, this->OrderGetSel());
 
				ShowDropDownMenu(this, _order_conditional_condition, o->GetConditionComparator(), ORDER_WIDGET_COND_COMPARATOR, 0, (o->GetConditionVariable() == OCV_REQUIRES_SERVICE) ? 0x3F : 0xC0);
 
			} break;
 

	
 
						case 1: OrderClick_NearestDepot(w, v, 0); break;
 
						case 2: OrderClick_Conditional(w, v, 0); break;
 
						default: NOT_REACHED();
 
					}
 
					break;
 
			case ORDER_WIDGET_COND_VALUE: {
 
				const Order *order = GetVehicleOrder(this->vehicle, this->OrderGetSel());
 
				uint value = order->GetConditionValue();
 
				if (order->GetConditionVariable() == OCV_MAX_SPEED) value = ConvertSpeedToDisplaySpeed(value);
 
				SetDParam(0, value);
 
				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_ORDER_CONDITIONAL_VALUE_CAPT, 5, 100, this, CS_NUMERAL);
 
			} break;
 

	
 
				case ORDER_WIDGET_COND_VARIABLE:
 
					DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), MOF_COND_VARIABLE | e->we.dropdown.index << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
			case ORDER_WIDGET_SHARED_ORDER_LIST:
 
				ShowVehicleListWindow(this->vehicle);
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnQueryTextFinished(char *str)
 
	{
 
		if (!StrEmpty(str)) {
 
			VehicleOrderID sel = this->OrderGetSel();
 
			uint value = atoi(str);
 

	
 
			switch (GetVehicleOrder(this->vehicle, sel)->GetConditionVariable()) {
 
				case OCV_MAX_SPEED:
 
					value = ConvertDisplaySpeedToSpeed(value);
 
					break;
 

	
 
				case ORDER_WIDGET_COND_COMPARATOR:
 
					DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), MOF_COND_COMPARATOR | e->we.dropdown.index << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
				case OCV_RELIABILITY:
 
				case OCV_LOAD_PERCENTAGE:
 
					value = Clamp(value, 0, 100);
 

	
 
				default:
 
					break;
 
			}
 
			break;
 
			DoCommandP(this->vehicle->tile, this->vehicle->index + (sel << 16), MOF_COND_VALUE | Clamp(value, 0, 2047) << 4, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
		}
 
	}
 

	
 
	virtual void OnDropdownSelect(int widget, int index)
 
	{
 
		switch (widget) {
 
			case ORDER_WIDGET_NON_STOP:
 
				OrderClick_Nonstop(this, index);
 
				break;
 

	
 
			case ORDER_WIDGET_FULL_LOAD:
 
				OrderClick_FullLoad(this, index);
 
				break;
 

	
 
			case ORDER_WIDGET_UNLOAD:
 
				OrderClick_Unload(this, index);
 
				break;
 

	
 
			case ORDER_WIDGET_GOTO:
 
				switch (index) {
 
					case 0:
 
						this->ToggleWidgetLoweredState(ORDER_WIDGET_GOTO);
 
						OrderClick_Goto(this, 0);
 
						break;
 

	
 
		case WE_DRAGDROP:
 
			switch (e->we.click.widget) {
 
				case ORDER_WIDGET_ORDER_LIST: {
 
					int from_order = OrderGetSel(w);
 
					int to_order = GetOrderFromOrderWndPt(w, e->we.dragdrop.pt.y, v);
 
					case 1: OrderClick_NearestDepot(this, 0); break;
 
					case 2: OrderClick_Conditional(this, 0); break;
 
					default: NOT_REACHED();
 
				}
 
				break;
 

	
 
			case ORDER_WIDGET_COND_VARIABLE:
 
				DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), MOF_COND_VARIABLE | index << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
				break;
 

	
 
			case ORDER_WIDGET_COND_COMPARATOR:
 
				DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), MOF_COND_COMPARATOR | index << 4,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 
				break;
 
		}
 
	}
 

	
 
					if (!(from_order == to_order || from_order == INVALID_ORDER || from_order > v->num_orders || to_order == INVALID_ORDER || to_order > v->num_orders) &&
 
							DoCommandP(v->tile, v->index, from_order | (to_order << 16), NULL, CMD_MOVE_ORDER | CMD_MSG(STR_CAN_T_MOVE_THIS_ORDER))) {
 
						WP(w, order_d).sel = -1;
 
					}
 
	virtual void OnDragDrop(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case ORDER_WIDGET_ORDER_LIST: {
 
				int from_order = this->OrderGetSel();
 
				int to_order = this->GetOrderFromPt(pt.y);
 

	
 
				} break;
 
				if (!(from_order == to_order || from_order == INVALID_ORDER || from_order > this->vehicle->num_orders || to_order == INVALID_ORDER || to_order > this->vehicle->num_orders) &&
 
						DoCommandP(this->vehicle->tile, this->vehicle->index, from_order | (to_order << 16), NULL, CMD_MOVE_ORDER | CMD_MSG(STR_CAN_T_MOVE_THIS_ORDER))) {
 
					this->selected_order = -1;
 
				}
 
			} break;
 

	
 
			case ORDER_WIDGET_DELETE:
 
				OrderClick_Delete(this, 0);
 
				break;
 
		}
 

	
 
				case ORDER_WIDGET_DELETE:
 
					OrderClick_Delete(w, v, 0);
 
					break;
 
		ResetObjectToPlace();
 
	}
 

	
 
	virtual bool OnKeyPress(uint16 key, uint16 keycode)
 
	{
 
		static const KeyToEvent keytoevent[] = {
 
			{'D', OrderClick_Skip},
 
			{'F', OrderClick_Delete},
 
			{'G', OrderClick_Goto},
 
			{'H', OrderClick_Nonstop},
 
			{'J', OrderClick_FullLoad},
 
			{'K', OrderClick_Unload},
 
			//{'?', OrderClick_Transfer},
 
			//('?', OrderClick_Service},
 
		};
 

	
 
		if (this->vehicle->owner != _local_player) return true;
 

	
 
		for (uint i = 0; i < lengthof(keytoevent); i++) {
 
			if (keycode == keytoevent[i].keycode) {
 
				keytoevent[i].proc(this, -1);
 
				return false;
 
			}
 

	
 
			ResetObjectToPlace();
 
			break;
 
		}
 
		return true;
 
	}
 

	
 
		case WE_KEYPRESS:
 
			if (v->owner != _local_player) break;
 
	virtual void OnPlaceObject(Point pt, TileIndex tile)
 
	{
 
		if (this->goto_type == OPOS_GOTO) {
 
			/* check if we're clicking on a vehicle first.. clone orders in that case. */
 
			const Vehicle *v = CheckMouseOverVehicle();
 
			if (v != NULL && this->HandleOrderVehClick(v)) return;
 

	
 
			const Order cmd = GetOrderCmdFromTile(this->vehicle, tile);
 
			if (!cmd.IsValid()) return;
 

	
 
			if (DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), cmd.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER))) {
 
				if (this->selected_order != -1) this->selected_order++;
 
				ResetObjectToPlace();
 
			}
 
		}
 
	}
 

	
 
			for (uint i = 0; i < lengthof(_order_keycodes); i++) {
 
				if (e->we.keypress.keycode == _order_keycodes[i]) {
 
					e->we.keypress.cont = false;
 
					/* see if the button is disabled */
 
					if (!w->IsWidgetDisabled(i + ORDER_WIDGET_SKIP)) _order_button_proc[i](w, v, -1);
 
					break;
 
	virtual void OnPlaceObjectAbort()
 
	{
 
		if (this->goto_type == OPOS_CONDITIONAL) {
 
			this->goto_type = OPOS_GOTO;
 
			if (_cursor.pos.x >= (this->left + this->widget[ORDER_WIDGET_ORDER_LIST].left) &&
 
					_cursor.pos.y >= (this->top  + this->widget[ORDER_WIDGET_ORDER_LIST].top) &&
 
					_cursor.pos.x <= (this->left + this->widget[ORDER_WIDGET_ORDER_LIST].right) &&
 
					_cursor.pos.y <= (this->top  + this->widget[ORDER_WIDGET_ORDER_LIST].bottom)) {
 
				int order_id = this->GetOrderFromPt(_cursor.pos.y - this->top);
 
				if (order_id != INVALID_ORDER) {
 
					Order order;
 
					order.next = NULL;
 
					order.index = 0;
 
					order.MakeConditional(order_id);
 

	
 
					DoCommandP(this->vehicle->tile, this->vehicle->index + (this->OrderGetSel() << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
 
				}
 
			}
 
			break;
 

	
 
		case WE_PLACE_OBJ:
 
			if (WP(w, order_d).goto_type == OPOS_GOTO) {
 
				OrdersPlaceObj(GetVehicle(w->window_number), e->we.place.tile, w);
 
			}
 
			break;
 

	
 
		case WE_ABORT_PLACE_OBJ:
 
			if (WP(w, order_d).goto_type == OPOS_CONDITIONAL) {
 
				WP(w, order_d).goto_type = OPOS_GOTO;
 
				if (_cursor.pos.x >= (w->left + w->widget[ORDER_WIDGET_ORDER_LIST].left) &&
 
						_cursor.pos.y >= (w->top  + w->widget[ORDER_WIDGET_ORDER_LIST].top) &&
 
						_cursor.pos.x <= (w->left + w->widget[ORDER_WIDGET_ORDER_LIST].right) &&
 
						_cursor.pos.y <= (w->top  + w->widget[ORDER_WIDGET_ORDER_LIST].bottom)) {
 
					int order_id = GetOrderFromOrderWndPt(w, _cursor.pos.y - w->top, v);
 
					if (order_id != INVALID_ORDER) {
 
						Order order;
 
						order.next = NULL;
 
						order.index = 0;
 
						order.MakeConditional(order_id);
 

	
 
						DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), order.Pack(), NULL, CMD_INSERT_ORDER | CMD_MSG(STR_8833_CAN_T_INSERT_NEW_ORDER));
 
					}
 
				}
 
			}
 
			w->RaiseWidget(ORDER_WIDGET_GOTO);
 
			w->InvalidateWidget(ORDER_WIDGET_GOTO);
 
			break;
 
		}
 
		this->RaiseWidget(ORDER_WIDGET_GOTO);
 
		this->InvalidateWidget(ORDER_WIDGET_GOTO);
 
	}
 

	
 
		/* check if a vehicle in a depot was clicked.. */
 
		case WE_MOUSELOOP:
 
			v = _place_clicked_vehicle;
 
			/*
 
			* Check if we clicked on a vehicle
 
			* and if the GOTO button of this window is pressed
 
			* This is because of all open order windows WE_MOUSELOOP is called
 
			* and if you have 3 windows open, and this check is not done
 
			* the order is copied to the last open window instead of the
 
			* one where GOTO is enabled
 
			*/
 
			if (v != NULL && w->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
				_place_clicked_vehicle = NULL;
 
				HandleOrderVehClick(GetVehicle(w->window_number), v, w);
 
			}
 
			break;
 
	virtual void OnMouseLoop()
 
	{
 
		const Vehicle *v = _place_clicked_vehicle;
 
		/*
 
		* Check if we clicked on a vehicle
 
		* and if the GOTO button of this window is pressed
 
		* This is because of all open order windows WE_MOUSELOOP is called
 
		* and if you have 3 windows open, and this check is not done
 
		* the order is copied to the last open window instead of the
 
		* one where GOTO is enabled
 
		*/
 
		if (v != NULL && this->IsWidgetLowered(ORDER_WIDGET_GOTO)) {
 
			_place_clicked_vehicle = NULL;
 
			this->HandleOrderVehClick(v);
 
		}
 
	}
 

	
 
		case WE_RESIZE:
 
			/* Update the scroll + matrix */
 
			w->vscroll.cap = (w->widget[ORDER_WIDGET_ORDER_LIST].bottom - w->widget[ORDER_WIDGET_ORDER_LIST].top) / 10;
 
			break;
 
	virtual void OnResize(Point new_size, Point delta)
 
	{
 
		/* Update the scroll + matrix */
 
		this->vscroll.cap = (this->widget[ORDER_WIDGET_ORDER_LIST].bottom - this->widget[ORDER_WIDGET_ORDER_LIST].top) / 10;
 
	}
 

	
 
		case WE_TIMEOUT: // handle button unclick ourselves...
 
			/* unclick all buttons except for the 'goto' button (ORDER_WIDGET_GOTO), which is 'persistent' */
 
			for (uint i = 0; i < w->widget_count; i++) {
 
				if (w->IsWidgetLowered(i) && i != ORDER_WIDGET_GOTO) {
 
					w->RaiseWidget(i);
 
					w->InvalidateWidget(i);
 
				}
 
	virtual void OnTimeout()
 
	{
 
		/* unclick all buttons except for the 'goto' button (ORDER_WIDGET_GOTO), which is 'persistent' */
 
		for (uint i = 0; i < this->widget_count; i++) {
 
			if (this->IsWidgetLowered(i) && i != ORDER_WIDGET_GOTO) {
 
				this->RaiseWidget(i);
 
				this->InvalidateWidget(i);
 
			}
 
			break;
 
		}
 
	}
 
}
 
};
 

	
 
/**
 
 * Widget definition for player train orders
 
@@ -1091,7 +1063,7 @@ static const WindowDesc _orders_train_de
 
	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 
	_orders_train_widgets,
 
	OrdersWndProc
 
	NULL
 
};
 

	
 
/**
 
@@ -1132,7 +1104,7 @@ static const WindowDesc _orders_desc = {
 
	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_RESIZABLE,
 
	_orders_widgets,
 
	OrdersWndProc
 
	NULL
 
};
 

	
 
/**
 
@@ -1173,27 +1145,19 @@ static const WindowDesc _other_orders_de
 
	WC_VEHICLE_ORDERS, WC_VEHICLE_VIEW,
 
	WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_RESIZABLE,
 
	_other_orders_widgets,
 
	OrdersWndProc
 
	NULL
 
};
 

	
 
void ShowOrdersWindow(const Vehicle *v)
 
{
 
	Window *w;
 
	VehicleID veh = v->index;
 

	
 
	DeleteWindowById(WC_VEHICLE_ORDERS, veh);
 
	DeleteWindowById(WC_VEHICLE_DETAILS, veh);
 

	
 
	if (v->owner != _local_player) {
 
		w = AllocateWindowDescFront<Window>(&_other_orders_desc, veh);
 
		new OrdersWindow(&_other_orders_desc, v);
 
	} else {
 
		w = AllocateWindowDescFront<Window>((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? &_orders_train_desc : &_orders_desc, veh);
 
	}
 

	
 
	if (w != NULL) {
 
		w->caption_color = v->owner;
 
		w->vscroll.cap = 6;
 
		w->resize.step_height = 10;
 
		WP(w, order_d).sel = -1;
 
		new OrdersWindow((v->type == VEH_TRAIN || v->type == VEH_ROAD) ? &_orders_train_desc : &_orders_desc, v);
 
	}
 
}
0 comments (0 inline, 0 general)