summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command.cpp3
-rw-r--r--src/command.h3
-rw-r--r--src/lang/english.txt1
-rw-r--r--src/order_cmd.cpp85
-rw-r--r--src/order_gui.cpp82
5 files changed, 168 insertions, 6 deletions
diff --git a/src/command.cpp b/src/command.cpp
index 49bfb3291..2b6946852 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -176,6 +176,8 @@ DEF_COMMAND(CmdAddSharedVehicleGroup);
DEF_COMMAND(CmdRemoveAllVehiclesGroup);
DEF_COMMAND(CmdSetGroupReplaceProtection);
+DEF_COMMAND(CmdMoveOrder);
+
/* The master command table */
static const Command _command_proc_table[] = {
{CmdBuildRailroadTrack, 0}, /* 0 */
@@ -328,6 +330,7 @@ static const Command _command_proc_table[] = {
{CmdAddSharedVehicleGroup, 0}, /* 124 */
{CmdRemoveAllVehiclesGroup, 0}, /* 125 */
{CmdSetGroupReplaceProtection, 0}, /* 126 */
+ {CmdMoveOrder, 0}, /* 127 */
};
/* This function range-checks a cmd, and checks if the cmd is not NULL */
diff --git a/src/command.h b/src/command.h
index 3279e458c..d13638d2d 100644
--- a/src/command.h
+++ b/src/command.h
@@ -143,6 +143,7 @@ enum {
CMD_MASS_START_STOP = 117,
CMD_DEPOT_SELL_ALL_VEHICLES = 118,
CMD_DEPOT_MASS_AUTOREPLACE = 119,
+
CMD_CREATE_GROUP = 120,
CMD_DELETE_GROUP = 121,
CMD_RENAME_GROUP = 122,
@@ -150,6 +151,8 @@ enum {
CMD_ADD_SHARED_VEHICLE_GROUP = 124,
CMD_REMOVE_ALL_VEHICLES_GROUP = 125,
CMD_SET_GROUP_REPLACE_PROTECTION = 126,
+
+ CMD_MOVE_ORDER = 127,
};
enum {
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 6353c4d2c..598568a39 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -2663,6 +2663,7 @@ STR_8832_TOO_MANY_ORDERS :{WHITE}Too many
STR_8833_CAN_T_INSERT_NEW_ORDER :{WHITE}Can't insert new order...
STR_8834_CAN_T_DELETE_THIS_ORDER :{WHITE}Can't delete this order...
STR_8835_CAN_T_MODIFY_THIS_ORDER :{WHITE}Can't modify this order...
+STR_CAN_T_MOVE_THIS_ORDER :{WHITE}Can't move this order...
STR_CAN_T_SKIP_ORDER :{WHITE}Can't skip current order...
STR_CAN_T_SKIP_TO_ORDER :{WHITE}Can't skip to selected order...
STR_8837_CAN_T_MOVE_VEHICLE :{WHITE}Can't move vehicle...
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index e6c0f3c84..34cfd0a5c 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -598,6 +598,91 @@ int32 CmdSkipToOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
return 0;
}
+/**
+ * Move an order inside the orderlist
+ * @param tile unused
+ * @param p1 the ID of the vehicle
+ * @param p2 order to move and target
+ * bit 0-15 : the order to move
+ * bit 16-31 : the target order
+ * @note The target order will move one place down in the orderlist
+ * if you move the order upwards else it'll move it one place down
+ */
+int32 CmdMoveOrder(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
+{
+ VehicleID veh = p1;
+ VehicleOrderID moving_order = GB(p2, 0, 16);
+ VehicleOrderID target_order = GB(p2, 16, 16);
+
+ if (!IsValidVehicleID(veh)) return CMD_ERROR;
+
+ Vehicle *v = GetVehicle(veh);
+ if (!CheckOwnership(v->owner)) return CMD_ERROR;
+
+ /* Don't make senseless movements */
+ if (moving_order >= v->num_orders || target_order >= v->num_orders ||
+ moving_order == target_order || v->num_orders <= 1)
+ return CMD_ERROR;
+
+ Order *moving_one = GetVehicleOrder(v, moving_order);
+ /* Don't move an empty order */
+ if (moving_one == NULL) return CMD_ERROR;
+
+ if (flags & DC_EXEC) {
+ /* Take the moving order out of the pointer-chain */
+ Order *one_before = GetVehicleOrder(v, moving_order - 1);
+ Order *one_past = GetVehicleOrder(v, moving_order + 1);
+
+ if (one_before == NULL) {
+ /* First order edit */
+ v->orders = moving_one->next;
+ } else {
+ one_before->next = moving_one->next;
+ }
+
+ /* Insert the moving_order again in the pointer-chain */
+ one_before = GetVehicleOrder(v, target_order - 1);
+ one_past = GetVehicleOrder(v, target_order);
+
+ moving_one->next = one_past;
+
+ if (one_before == NULL) {
+ /* first order edit */
+ SwapOrders(v->orders, moving_one);
+ v->orders->next = moving_one;
+ } else {
+ one_before->next = moving_one;
+ }
+
+ /* Update shared list */
+ Vehicle *u = GetFirstVehicleFromSharedList(v);
+
+ DeleteOrderWarnings(u);
+
+ for (; u != NULL; u = u->next_shared) {
+ /* Update the first order */
+ if (u->orders != v->orders) u->orders = v->orders;
+
+ /* Update the current order */
+ if (u->cur_order_index == moving_order) {
+ u->cur_order_index = target_order;
+ } else if(u->cur_order_index > moving_order && u->cur_order_index <= target_order) {
+ u->cur_order_index--;
+ } else if(u->cur_order_index < moving_order && u->cur_order_index >= target_order) {
+ u->cur_order_index++;
+ }
+
+ assert(v->orders == u->orders);
+ /* Update any possible open window of the vehicle */
+ InvalidateVehicleOrder(u);
+ }
+
+ /* Make sure to rebuild the whole list */
+ RebuildVehicleLists();
+ }
+
+ return 0;
+}
/** Modify an order in the orderlist of a vehicle.
* @param tile unused
diff --git a/src/order_gui.cpp b/src/order_gui.cpp
index dbb493287..3f1ab718e 100644
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -44,6 +44,13 @@ enum OrderWindowWidgets {
ORDER_WIDGET_RESIZE,
};
+/**
+ * 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);
@@ -52,6 +59,33 @@ static int OrderGetSel(const Window *w)
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 - 15) / 10;
+
+ if ((uint)sel >= w->vscroll.cap) return INVALID_ORDER;
+
+ sel += w->vscroll.pos;
+
+ return (sel <= v->num_orders && sel >= 0) ? sel : INVALID_ORDER;
+}
+
static StringID StationOrderStrings[] = {
STR_8806_GO_TO,
STR_8807_GO_TO_TRANSFER,
@@ -513,14 +547,14 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
break;
case WE_CLICK: {
- Vehicle *v = GetVehicle(w->window_number);
+ const Vehicle *v = GetVehicle(w->window_number);
switch (e->we.click.widget) {
case ORDER_WIDGET_ORDER_LIST: {
- int sel = (e->we.click.pt.y - 15) / 10;
+ ResetObjectToPlace();
- if ((uint)sel >= w->vscroll.cap) return;
+ int sel = GetOrderFromOrderWndPt(w, e->we.click.pt.y, v);
- sel += w->vscroll.pos;
+ if (sel == INVALID_ORDER) return;
if (_ctrl_pressed && sel < v->num_orders) {
const Order *ord = GetVehicleOrder(v, sel);
@@ -535,10 +569,21 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
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 (v->owner == _local_player) {
+ /* Activate drag and drop */
+ SetObjectToPlaceWnd(SPR_CURSOR_MOUSE, PAL_NONE, 4, w);
+ }
+ }
}
- if (sel == WP(w,order_d).sel) sel = -1;
- WP(w,order_d).sel = sel;
SetWindowDirty(w);
} break;
@@ -578,6 +623,31 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
}
} break;
+ case WE_DRAGDROP: {
+ const Vehicle *v = GetVehicle(w->window_number);
+
+ 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);
+
+ 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;
+ }
+
+ break;
+ }
+
+ case ORDER_WIDGET_DELETE:
+ OrderClick_Delete(w, v);
+ break;
+ }
+
+ ResetObjectToPlace();
+ break;
+ }
+
case WE_KEYPRESS: {
Vehicle *v = GetVehicle(w->window_number);
uint i;