changeset 15253:bd9b4d0ad9fe draft

(svn r19888) -Add [FS#3705]: Add highlighting of drag destination in depot gui (sbr).
author alberth <alberth@openttd.org>
date Sun, 23 May 2010 15:02:26 +0000
parents f422122b47a6
children 49205e8f96b8
files src/depot_gui.cpp src/train_gui.cpp src/vehicle_gui.h
diffstat 3 files changed, 89 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/depot_gui.cpp
+++ b/src/depot_gui.cpp
@@ -213,6 +213,7 @@
 
 struct DepotWindow : Window {
 	VehicleID sel;
+	VehicleID vehicle_over; ///< Rail vehicle over which another one is dragged, \c INVALID_VEHICLE if none.
 	VehicleType type;
 	bool generate_list;
 	VehicleList vehicle_list;
@@ -223,6 +224,7 @@
 		assert(IsCompanyBuildableVehicleType(type)); // ensure that we make the call with a valid type
 
 		this->sel = INVALID_VEHICLE;
+		this->vehicle_over = INVALID_VEHICLE;
 		this->generate_list = true;
 		this->type = type;
 
@@ -263,7 +265,8 @@
 				free_wagon = u->IsFreeWagon();
 
 				uint x_space = free_wagon ? TRAININFO_DEFAULT_VEHICLE_WIDTH : 0;
-				DrawTrainImage(u, image_left + (rtl ? 0 : x_space), image_right - (rtl ? x_space : 0), sprite_y - 1, this->sel, free_wagon ? 0 : this->hscroll.GetPosition());
+				DrawTrainImage(u, image_left + (rtl ? 0 : x_space), image_right - (rtl ? x_space : 0), sprite_y - 1,
+						this->sel, free_wagon ? 0 : this->hscroll.GetPosition(), this->vehicle_over);
 
 				/* Number of wagons relative to a standard length wagon (rounded up) */
 				SetDParam(0, CeilDiv(u->tcache.cached_total_length, 8));
@@ -862,6 +865,7 @@
 
 		/* abort drag & drop */
 		this->sel = INVALID_VEHICLE;
+		this->vehicle_over = INVALID_VEHICLE;
 		this->SetWidgetDirty(DEPOT_WIDGET_MATRIX);
 	};
 
@@ -877,6 +881,46 @@
 		}
 	}
 
+	virtual void OnMouseDrag(Point pt, int widget)
+	{
+		if (this->type != VEH_TRAIN || this->sel == INVALID_VEHICLE) return;
+
+		/* A rail vehicle is dragged.. */
+		if (widget != DEPOT_WIDGET_MATRIX) { // ..outside of the depot matrix.
+			if (this->vehicle_over != INVALID_VEHICLE) {
+				this->vehicle_over = INVALID_VEHICLE;
+				this->SetWidgetDirty(DEPOT_WIDGET_MATRIX);
+			}
+			return;
+		}
+
+		NWidgetBase *matrix = this->GetWidget<NWidgetBase>(widget);
+		const Vehicle *v = NULL;
+		GetDepotVehiclePtData gdvp = {NULL, NULL};
+
+		if (this->GetVehicleFromDepotWndPt(pt.x - matrix->pos_x, pt.y - matrix->pos_y, &v, &gdvp) != MODE_DRAG_VEHICLE) return;
+
+		VehicleID new_vehicle_over = INVALID_VEHICLE;
+		if (gdvp.head != NULL) {
+			if (gdvp.wagon == NULL && gdvp.head->Last()->index != this->sel) { // ..at the end of the train.
+				/* NOTE: As a wagon can't be moved at the begin of a train, head index isn't used to mark a drag-and-drop
+				 * destination inside a train. This head index is then used to indicate that a wagon is inserted at
+				 * the end of the train.
+				 */
+				new_vehicle_over = gdvp.head->index;
+			} else if (gdvp.wagon != NULL && gdvp.head != gdvp.wagon &&
+					gdvp.wagon->index != this->sel &&
+					gdvp.wagon->Previous()->index != this->sel) { // ..over an existing wagon.
+				new_vehicle_over = gdvp.wagon->index;
+			}
+		}
+
+		if (this->vehicle_over == new_vehicle_over) return;
+
+		this->vehicle_over = new_vehicle_over;
+		this->SetWidgetDirty(widget);
+	}
+
 	virtual void OnDragDrop(Point pt, int widget)
 	{
 		switch (widget) {
@@ -896,6 +940,7 @@
 							DoCommandP(Vehicle::Get(sel)->tile, Vehicle::Get(sel)->index, true,
 									CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_REVERSE_DIRECTION_RAIL_VEHICLE));
 						} else if (gdvp.wagon == NULL || gdvp.wagon->index != sel) {
+							this->vehicle_over = INVALID_VEHICLE;
 							TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
 						} else if (gdvp.head != NULL && Train::From(gdvp.head)->IsFrontEngine()) {
 							ShowVehicleViewWindow(gdvp.head);
--- a/src/train_gui.cpp
+++ b/src/train_gui.cpp
@@ -49,6 +49,33 @@
 }
 
 /**
+ * Highlight the position where a rail vehicle is dragged over by drawing a light gray background.
+ * @param px        The current x position to draw from.
+ * @param max_width The maximum space available to draw.
+ * @param selection Selected vehicle that is dragged.
+ * @return The width of the highlight mark.
+ */
+static uint HighlightDragPosition(int px, int max_width, VehicleID selection)
+{
+	bool rtl = _dynlang.text_dir == TD_RTL;
+
+	assert(selection != INVALID_VEHICLE);
+	Point offset;
+	int dragged_width = Train::Get(selection)->GetDisplayImageWidth(&offset) + WD_FRAMERECT_LEFT + WD_FRAMERECT_RIGHT;
+
+	int drag_hlight_left = rtl ? max(px -dragged_width, 0) : px;
+	int drag_hlight_right = rtl ? px : min(px + dragged_width, max_width);
+	int drag_hlight_width = max(drag_hlight_right - drag_hlight_left, 0);
+
+	if (drag_hlight_width > 0) {
+		GfxFillRect(drag_hlight_left + WD_FRAMERECT_LEFT, WD_FRAMERECT_TOP + 1,
+				drag_hlight_right - WD_FRAMERECT_RIGHT, 13 - WD_FRAMERECT_BOTTOM, _colour_gradient[COLOUR_GREY][7]);
+	}
+
+	return drag_hlight_width;
+}
+
+/**
  * Draws an image of a whole train
  * @param v         Front vehicle
  * @param left      The minimum horizontal position
@@ -56,8 +83,9 @@
  * @param y         Vertical position to draw at
  * @param selection Selected vehicle to draw a frame around
  * @param skip      Number of pixels to skip at the front (for scrolling)
+ * @param drag_dest The vehicle another one is dragged over, \c INVALID_VEHICLE if none.
  */
-void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, int skip)
+void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, int skip, VehicleID drag_dest)
 {
 	bool rtl = _dynlang.text_dir == TD_RTL;
 	Direction dir = rtl ? DIR_E : DIR_W;
@@ -75,7 +103,15 @@
 
 	int px = rtl ? max_width + skip : -skip;
 	bool sel_articulated = false;
+	bool dragging = (drag_dest != INVALID_VEHICLE);
+	bool drag_at_end_of_train = (drag_dest == v->index); // Head index is used to mark dragging at end of train.
 	for (; v != NULL && (rtl ? px > 0 : px < max_width); v = v->Next()) {
+		if (dragging && !drag_at_end_of_train && drag_dest == v->index) {
+			/* Highlight the drag-and-drop destination inside the train. */
+			uint drag_hlight_width = HighlightDragPosition(px, max_width, selection);
+			px += rtl ? -drag_hlight_width : drag_hlight_width;
+		}
+
 		Point offset;
 		int width = Train::From(v)->GetDisplayImageWidth(&offset);
 
@@ -102,6 +138,11 @@
 		px += rtl ? -width : width;
 	}
 
+	if (dragging && drag_at_end_of_train) {
+		/* Highlight the drag-and-drop destination at the end of the train. */
+		HighlightDragPosition(px, max_width, selection);
+	}
+
 	if (highlight_l != highlight_r) {
 		/* Draw the highlight. Now done after drawing all the engines, as
 		 * the next engine after the highlight could overlap it. */
--- a/src/vehicle_gui.h
+++ b/src/vehicle_gui.h
@@ -64,7 +64,7 @@
 
 int DrawVehiclePurchaseInfo(int left, int right, int y, EngineID engine_number);
 
-void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, int skip);
+void DrawTrainImage(const Train *v, int left, int right, int y, VehicleID selection, int skip, VehicleID drag_dest = INVALID_VEHICLE);
 void DrawRoadVehImage(const Vehicle *v, int left, int right, int y, VehicleID selection);
 void DrawShipImage(const Vehicle *v, int left, int right, int y, VehicleID selection);
 void DrawAircraftImage(const Vehicle *v, int left, int right, int y, VehicleID selection);