changeset 9258:1cd16b63b893 draft

(svn r13124) -Codechange: make a class of the OrdersWindow.
author glx <glx@openttd.org>
date Fri, 16 May 2008 20:08:20 +0000
parents 2216e638534b
children eaa1bd5adde5
files src/order_gui.cpp
diffstat 1 files changed, 612 insertions(+), 648 deletions(-) [+]
line wrap: on
line diff
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -58,60 +58,6 @@
 	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 @@
 }
 
 
-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 @@
 	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 @@
 	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 @@
 	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 @@
 	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);
 	}
 }