r5930 - trunk/eda/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Sat Apr 24 00:01:56 CEST 2010


Author: werner
Date: 2010-04-24 00:01:56 +0200 (Sat, 24 Apr 2010)
New Revision: 5930

Modified:
   trunk/eda/fped/gui_canvas.c
   trunk/eda/fped/gui_frame.c
   trunk/eda/fped/gui_frame_drag.c
   trunk/eda/fped/gui_frame_drag.h
Log:
Working towards the dragging of frames. Changed the press/drag/release logic of
tables such that items are selected on release and we can thus drag without
selecting. (From a user point of view, selecting would be fine. But selecting 
may sometimes cause a change_world or similar, destroying the widget, which 
upsets drag and drop.)

- gui_frame_drag.c (setup_var_drag, setup_value_drag): moved targets to file
  scope
- gui_frame_drag.c (has_target, drag_var_motion, drag_value_motion): Gtk
  doesn't check target compatibility for us, so we have to do this explicitly
- gui_frame_drag.c (drag_begin): don't leak the pixbuf
- gui_frame_drag.c (is_dragging, drag_end), gui_frame_drag.h: for drag vs.
  activations on button release, we now can test what is being dragged. For
  this, we have to explicitly clear the variable "dragging" when done.
- gui_frame_drag.c (setup_var_drag, setup_value_drag): moved common setup to
  setup_drag_common
- gui_frame_drag.c (setup_frame_drag, drag_frame_motion), gui_frame_drag.h, 
  gui_frame.c (frame_select_event, build_frame_label): added infrastructure for
  dragging frames
- gui_frame_drag.c (setup_canvas_drag, drag_canvas_motion), gui_frame_drag.h,
  gui_canvas.c (motion_notify_event, make_canvas): added infrastructure for
  dragging to the canvas
- gui_frame.c (table_var_select_event, table_value_select_event, build_table):
  split logic into press and release action, so that we can drag without
  implicitly selecting



Modified: trunk/eda/fped/gui_canvas.c
===================================================================
--- trunk/eda/fped/gui_canvas.c	2010-04-23 13:43:19 UTC (rev 5929)
+++ trunk/eda/fped/gui_canvas.c	2010-04-23 22:01:56 UTC (rev 5930)
@@ -24,6 +24,7 @@
 #include "gui_status.h"
 #include "gui_tool.h"
 #include "gui.h"
+#include "gui_frame_drag.h"
 #include "gui_canvas.h"
 
 
@@ -182,7 +183,7 @@
 	if (event->state & GDK_BUTTON2_MASK)
 		drag_middle(pos);
 	update_pos(pos);
-	return TRUE;
+	return FALSE;
 }
 
 
@@ -541,6 +542,8 @@
 
 	gtk_widget_set_double_buffered(canvas, FALSE);
 
+	setup_canvas_drag(canvas);
+
 	draw_ctx.widget = canvas;
 
 	return canvas;

Modified: trunk/eda/fped/gui_frame.c
===================================================================
--- trunk/eda/fped/gui_frame.c	2010-04-23 13:43:19 UTC (rev 5929)
+++ trunk/eda/fped/gui_frame.c	2010-04-23 22:01:56 UTC (rev 5930)
@@ -886,30 +886,59 @@
 }
 
 
-static gboolean table_var_select_event(GtkWidget *widget,
+static gboolean table_var_press_event(GtkWidget *widget,
     GdkEventButton *event, gpointer data)
 {
 	struct var *var = data;
 
 	switch (event->button) {
+	case 3:
+		pop_up_table_var(var, event);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+static gboolean table_var_release_event(GtkWidget *widget,
+    GdkEventButton *event, gpointer data)
+{
+	struct var *var = data;
+
+	switch (event->button) {
 	case 1:
+		if (is_dragging(var))
+			return FALSE;
 		edit_var(var, set_col_values, var, -1);
-		return FALSE;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+static gboolean table_value_press_event(GtkWidget *widget,
+    GdkEventButton *event, gpointer data)
+{
+	struct value *value = data;
+
+	switch (event->button) {
 	case 3:
-		pop_up_table_var(var, event);
-		break;
+		pop_up_table_value(value, event);
+		return TRUE;
 	}
-	return TRUE;
+	return FALSE;
 }
 
 
-static gboolean table_value_select_event(GtkWidget *widget,
+static gboolean table_value_release_event(GtkWidget *widget,
     GdkEventButton *event, gpointer data)
 {
 	struct value *value = data;
 
 	switch (event->button) {
 	case 1:
+		if (is_dragging(value))
+			return FALSE;
 		if (!value->row ||
 		    value->row->table->active_row == value->row) {
 			edit_nothing();
@@ -919,12 +948,9 @@
 			select_row(value->row);
 			change_world();
 		}
-		return FALSE;
-	case 3:
-		pop_up_table_value(value, event);
-		break;
+		return TRUE;
 	}
-	return TRUE;
+	return FALSE;
 }
 
 
@@ -1009,8 +1035,11 @@
 		label_in_box_bg(field, COLOR_VAR_PASSIVE);
 		g_signal_connect(G_OBJECT(box_of_label(field)),
 		    "button_press_event",
-		    G_CALLBACK(table_var_select_event), var);
+		    G_CALLBACK(table_var_press_event), var);
 		g_signal_connect(G_OBJECT(box_of_label(field)),
+		    "button_release_event",
+		    G_CALLBACK(table_var_release_event), var);
+		g_signal_connect(G_OBJECT(box_of_label(field)),
 		    "scroll_event",
 		    G_CALLBACK(table_scroll_event), table);
 		var->widget = field;
@@ -1034,8 +1063,11 @@
 			    COLOR_ROW_SELECTED : COLOR_ROW_UNSELECTED);
 			g_signal_connect(G_OBJECT(box_of_label(field)),
 			    "button_press_event",
-			    G_CALLBACK(table_value_select_event), value);
+			    G_CALLBACK(table_value_press_event), value);
 			g_signal_connect(G_OBJECT(box_of_label(field)),
+			    "button_release_event",
+			    G_CALLBACK(table_value_release_event), value);
+			g_signal_connect(G_OBJECT(box_of_label(field)),
 			    "scroll_event",
 			    G_CALLBACK(table_scroll_event), table);
 			value->widget = field;
@@ -1653,13 +1685,29 @@
 }
 
 
-static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event,
+static gboolean frame_press_event(GtkWidget *widget, GdkEventButton *event,
     gpointer data)
 {
 	struct frame *frame = data;
 
 	switch (event->button) {
+	case 3:
+		pop_up_frame(frame, event);
+		return TRUE;
+	}
+	return FALSE;
+}
+
+
+static gboolean frame_release_event(GtkWidget *widget, GdkEventButton *event,
+    gpointer data)
+{
+	struct frame *frame = data;
+
+	switch (event->button) {
 	case 1:
+		if (is_dragging(frame))
+			return FALSE;
 		if (active_frame != frame)
 			select_frame(frame);
 		else {
@@ -1668,12 +1716,9 @@
 				edit_frame(frame);
 			}
 		}
-		break;
-	case 3:
-		pop_up_frame(frame, event);
-		break;
+		return TRUE;
 	}
-	return TRUE;
+	return FALSE;
 }
 
 
@@ -1691,9 +1736,13 @@
 	    COLOR_FRAME_SELECTED : COLOR_FRAME_UNSELECTED);
 
 	g_signal_connect(G_OBJECT(box_of_label(label)),
-	    "button_press_event", G_CALLBACK(frame_select_event), frame);
+	    "button_press_event", G_CALLBACK(frame_press_event), frame);
+	g_signal_connect(G_OBJECT(box_of_label(label)),
+	    "button_release_event", G_CALLBACK(frame_release_event), frame);
 	frame->label = label;
 
+	setup_frame_drag(frame);
+
 	return box_of_label(label);
 }
 

Modified: trunk/eda/fped/gui_frame_drag.c
===================================================================
--- trunk/eda/fped/gui_frame_drag.c	2010-04-23 13:43:19 UTC (rev 5929)
+++ trunk/eda/fped/gui_frame_drag.c	2010-04-23 22:01:56 UTC (rev 5930)
@@ -18,12 +18,49 @@
 #include "gui_frame_drag.h"
 
 
+enum {
+	target_id_var,
+	target_id_value,
+	target_id_frame,
+	target_id_canvas,
+};
+
+
+static GtkTargetEntry target_var = {
+	.target = "var",
+	.flags  = GTK_TARGET_SAME_APP,
+	.info	= target_id_var,
+};
+
+static GtkTargetEntry target_value = {
+	.target = "value",
+	.flags  = GTK_TARGET_SAME_APP,
+	.info	= target_id_value,
+};
+
+static GtkTargetEntry target_frame = {
+	.target = "frame",
+	.flags  = GTK_TARGET_SAME_APP,
+	.info	= target_id_frame,
+};
+
+
+/* ----- dragging status --------------------------------------------------- */
+
+
 /*
- * Pointer to whatever it is we're dragging. Undefined if not dragging.
+ * Pointer to whatever it is we're dragging. NULL if not dragging.
  */
+
 static void *dragging;
 
 
+int is_dragging(void *this)
+{
+	return this == dragging;
+}
+
+
 /* ----- helper functions for indexed list and swapping -------------------- */
 
 
@@ -148,9 +185,29 @@
 }
 
 
-/* ----- common callback --------------------------------------------------- */
+/* ----- common functions -------------------------------------------------- */
 
 
+/*
+ * according to
+ * http://www.pubbs.net/201004/gtk/22819-re-drag-and-drop-drag-motion-cursor-lockup-fixed-.html
+ * http://www.cryingwolf.org/articles/gtk-dnd.html
+ */
+
+static int has_target(GtkWidget *widget, GdkDragContext *drag_context,
+    const char *name)
+{
+	GdkAtom target;
+
+	target = gtk_drag_dest_find_target(widget, drag_context, NULL);
+
+	/*
+	 * Force allocation so that we don't have to check for GDK_NONE.
+	 */
+	return target == gdk_atom_intern(name, FALSE);
+}
+
+
 static void drag_begin(GtkWidget *widget,
     GtkTextDirection previous_direction, gpointer user_data)
 {
@@ -163,11 +220,28 @@
 	pixbuf =
 	    gdk_pixbuf_get_from_drawable(NULL, DA, NULL, 0, 0, 0, 0, 1, 1);
 	gtk_drag_source_set_icon_pixbuf(widget, pixbuf);
+	g_object_unref(pixbuf);
 
 	dragging = user_data;
 }
 
 
+static void drag_end(GtkWidget *widget, GdkDragContext *drag_context,
+    gpointer user_data)
+{
+	dragging = NULL;
+}
+
+
+static void setup_drag_common(GtkWidget *widget, void *user_arg)
+{
+	g_signal_connect(G_OBJECT(widget), "drag-begin",
+	    G_CALLBACK(drag_begin), user_arg);
+	g_signal_connect(G_OBJECT(widget), "drag-end",
+	    G_CALLBACK(drag_end), user_arg);
+}
+
+
 /* ----- drag variables ---------------------------------------------------- */
 
 
@@ -179,6 +253,8 @@
 	struct var *to = user_data;
 	int from_n, to_n, i;
 
+	if (!has_target(widget, drag_context, "var"))
+		return FALSE;
 	if (from == to || from->table != to->table)
 		return FALSE;
 	from_n = NDX(from->table->vars, from);
@@ -192,19 +268,14 @@
 
 void setup_var_drag(struct var *var)
 {
-	static GtkTargetEntry target = {
-		.target = "var",
-		.flags  = GTK_TARGET_SAME_APP,
-	};
 	GtkWidget *box;
 
 	box = box_of_label(var->widget);
 	gtk_drag_source_set(box, GDK_BUTTON1_MASK,
-	    &target, 1, GDK_ACTION_PRIVATE);
+	    &target_var, 1, GDK_ACTION_PRIVATE);
 	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_HIGHLIGHT,
-	    &target, 1, GDK_ACTION_PRIVATE);
-	g_signal_connect(G_OBJECT(box), "drag-begin",
-	    G_CALLBACK(drag_begin), var);
+	    &target_var, 1, GDK_ACTION_PRIVATE);
+	setup_drag_common(box, var);
 	g_signal_connect(G_OBJECT(box), "drag-motion",
 	    G_CALLBACK(drag_var_motion), var);
 }
@@ -219,10 +290,13 @@
 {
 	struct value *from = dragging;
 	struct value *to = user_data;
-	struct table *table = from->row->table;
+	struct table *table;
 	struct row **row, *end;
 	int from_n, to_n, i;
 
+	if (!has_target(widget, drag_context, "value"))
+		return FALSE;
+	table = from->row->table;
 	if (table != to->row->table)
 		return FALSE;
 
@@ -263,19 +337,65 @@
 
 void setup_value_drag(struct value *value)
 {
-	static GtkTargetEntry target = {
-		.target = "value",
-		.flags  = GTK_TARGET_SAME_APP,
-	};
 	GtkWidget *box;
 
 	box = box_of_label(value->widget);
 	gtk_drag_source_set(box, GDK_BUTTON1_MASK,
-	    &target, 1, GDK_ACTION_PRIVATE);
+	    &target_value, 1, GDK_ACTION_PRIVATE);
 	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_HIGHLIGHT,
-	    &target, 1, GDK_ACTION_PRIVATE);
-	g_signal_connect(G_OBJECT(box), "drag-begin",
-	    G_CALLBACK(drag_begin), value);
+	    &target_value, 1, GDK_ACTION_PRIVATE);
+	setup_drag_common(box, value);
 	g_signal_connect(G_OBJECT(box), "drag-motion",
 	    G_CALLBACK(drag_value_motion), value);
 }
+
+
+/* ----- drag frame labels ------------------------------------------------- */
+
+
+static gboolean drag_frame_motion(GtkWidget *widget,
+    GdkDragContext *drag_context, gint x, gint y, guint time_,
+    gpointer user_data)
+{
+	if (!has_target(widget, drag_context, "frame"))
+		return FALSE;
+//fprintf(stderr, "frame\n");
+return FALSE;
+}
+
+
+void setup_frame_drag(struct frame *frame)
+{
+	GtkWidget *box;
+
+	box = box_of_label(frame->label);
+	gtk_drag_source_set(box, GDK_BUTTON1_MASK,
+	    &target_frame, 1, GDK_ACTION_PRIVATE);
+	setup_drag_common(box, frame);
+	g_signal_connect(G_OBJECT(box), "drag-motion",
+	    G_CALLBACK(drag_frame_motion), frame);
+}
+
+
+/* ----- drag to the canvas ------------------------------------------------ */
+
+
+static gboolean drag_canvas_motion(GtkWidget *widget,
+    GdkDragContext *drag_context, gint x, gint y, guint time_,
+    gpointer user_data)
+{
+	if (!has_target(widget, drag_context, "frame"))
+		return FALSE;
+//fprintf(stderr, "canvas\n");
+return FALSE;
+}
+
+
+void setup_canvas_drag(GtkWidget *canvas)
+{
+	gtk_drag_dest_set(canvas, GTK_DEST_DEFAULT_HIGHLIGHT,
+	    &target_frame, 1, GDK_ACTION_PRIVATE);
+	setup_drag_common(canvas, NULL);
+	g_signal_connect(G_OBJECT(canvas), "drag-motion",
+	    G_CALLBACK(drag_canvas_motion), NULL);
+}

Modified: trunk/eda/fped/gui_frame_drag.h
===================================================================
--- trunk/eda/fped/gui_frame_drag.h	2010-04-23 13:43:19 UTC (rev 5929)
+++ trunk/eda/fped/gui_frame_drag.h	2010-04-23 22:01:56 UTC (rev 5930)
@@ -19,7 +19,11 @@
 #include "obj.h"
 
 
+int is_dragging(void *this);
+
 void setup_var_drag(struct var *var);
 void setup_value_drag(struct value *value);
+void setup_frame_drag(struct frame *frame);
+void setup_canvas_drag(GtkWidget *canvas);
 
 #endif /* !GUI_FRAME_DRAG_H */




More information about the commitlog mailing list