r5932 - trunk/eda/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Sat Apr 24 23:46:44 CEST 2010


Author: werner
Date: 2010-04-24 23:46:43 +0200 (Sat, 24 Apr 2010)
New Revision: 5932

Modified:
   trunk/eda/fped/gui_canvas.c
   trunk/eda/fped/gui_canvas.h
   trunk/eda/fped/gui_frame_drag.c
   trunk/eda/fped/gui_frame_drag.h
   trunk/eda/fped/gui_tool.c
   trunk/eda/fped/gui_tool.h
Log:
Dragging a frame into the canvas now works. It's built on top of the frame
tool, with all the old code still around, so the code paths are a bit obscure.

- gui_frame_drag.c: use GTK_DEST_DEFAULT_MOTION instead of
  GTK_DEST_DEFAULT_HIGHLIGHT
- gui_frame_drag.c: put meat on the frame and canvas drag and drop skeleton
- gui_frame_drag.c (setup_frame_drag, setup_canvas_drag): use GDK_ACTION_COPY
  instead of GDK_ACTION_PRIVATE
- gui_frame_drag.h, gui_frame_drag.c (is_dragging_anything): new helper
  function to check if we're dragging anything, without specifying what
- gui_canvas.h, gui_canvas.c: added thin interface layer between gui_frame.c 
  and gui_tool.c
- gui_canvas.c (enter_notify_event, leave_notify_event): return FALSE so that
  other widgets can get the events, too
- gui_tool.h, gui_tool.c (tool_hover): return whether we found anything to 
  hover on
- gui_tool.h, gui_tool.c: added interface for dropping a frame on the canvas



Modified: trunk/eda/fped/gui_canvas.c
===================================================================
--- trunk/eda/fped/gui_canvas.c	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_canvas.c	2010-04-24 21:46:43 UTC (rev 5932)
@@ -187,6 +187,41 @@
 }
 
 
+/* ----- drag and drop (frame to canvas) ----------------------------------- */
+
+
+void canvas_frame_begin(struct frame *frame)
+{
+	tool_push_frame(frame);
+}
+
+
+int canvas_frame_motion(struct frame *frame, int x, int y)
+{
+	struct coord pos = canvas_to_coord(x, y);
+
+	return tool_hover(pos);
+}
+
+
+void canvas_frame_end(void)
+{
+	tool_dehover();
+	tool_pop_frame();
+}
+
+
+int canvas_frame_drop(struct frame *frame, int x, int y)
+{
+	struct coord pos = canvas_to_coord(x, y);
+
+	if (!tool_place_frame(frame, pos))
+		return FALSE;
+	change_world();
+	return TRUE;
+}
+
+
 /* ----- button press and release ------------------------------------------ */
 
 
@@ -254,6 +289,8 @@
 	DPRINTF("--- button release ---");
 	switch (event->button) {
 	case 1:
+		if (is_dragging_anything())
+			return FALSE;
 		if (!dragging)
 			break;
 		drag_left(pos);
@@ -448,8 +485,9 @@
 static gboolean enter_notify_event(GtkWidget *widget, GdkEventCrossing *event,
     gpointer data)
 {
+	DPRINTF("--- enter ---");
 	gtk_widget_grab_focus(widget);
-	return TRUE;
+	return FALSE;
 }
 
 
@@ -461,7 +499,7 @@
 		tool_cancel_drag();
 	tool_dehover();
 	dragging = 0;
-	return TRUE;
+	return FALSE;
 }
 
 

Modified: trunk/eda/fped/gui_canvas.h
===================================================================
--- trunk/eda/fped/gui_canvas.h	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_canvas.h	2010-04-24 21:46:43 UTC (rev 5932)
@@ -1,8 +1,8 @@
 /*
  * gui_canvas.h - GUI, canvas
  *
- * Written 2009 by Werner Almesberger
- * Copyright 2009 by Werner Almesberger
+ * Written 2009, 2010 by Werner Almesberger
+ * Copyright 2009, 2010 by Werner Almesberger
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -34,6 +34,11 @@
 void zoom_to_frame(void);
 void zoom_to_extents(void);
 
+void canvas_frame_begin(struct frame *frame);
+int canvas_frame_motion(struct frame *frame, int x, int y);
+void canvas_frame_end(void);
+int canvas_frame_drop(struct frame *frame, int x, int y);
+
 GtkWidget *make_canvas(void);
 void init_canvas(void);
 

Modified: trunk/eda/fped/gui_frame_drag.c
===================================================================
--- trunk/eda/fped/gui_frame_drag.c	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_frame_drag.c	2010-04-24 21:46:43 UTC (rev 5932)
@@ -15,9 +15,15 @@
 
 #include "obj.h"
 #include "gui_util.h"
+#include "gui.h"
+#include "gui_canvas.h"
 #include "gui_frame_drag.h"
 
+#if 0
+#include "icons/frame.xpm"
+#endif
 
+
 enum {
 	target_id_var,
 	target_id_value,
@@ -61,6 +67,12 @@
 }
 
 
+int is_dragging_anything(void)
+{
+	return !!dragging;
+}
+
+
 /* ----- helper functions for indexed list and swapping -------------------- */
 
 
@@ -273,7 +285,7 @@
 	box = box_of_label(var->widget);
 	gtk_drag_source_set(box, GDK_BUTTON1_MASK,
 	    &target_var, 1, GDK_ACTION_PRIVATE);
-	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_HIGHLIGHT,
+	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_MOTION,
 	    &target_var, 1, GDK_ACTION_PRIVATE);
 	setup_drag_common(box, var);
 	g_signal_connect(G_OBJECT(box), "drag-motion",
@@ -342,7 +354,7 @@
 	box = box_of_label(value->widget);
 	gtk_drag_source_set(box, GDK_BUTTON1_MASK,
 	    &target_value, 1, GDK_ACTION_PRIVATE);
-	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_HIGHLIGHT,
+	gtk_drag_dest_set(box, GTK_DEST_DEFAULT_MOTION,
 	    &target_value, 1, GDK_ACTION_PRIVATE);
 	setup_drag_common(box, value);
 	g_signal_connect(G_OBJECT(box), "drag-motion",
@@ -350,28 +362,86 @@
 }
 
 
+/* ----- frame to canvas helper functions ---------------------------------- */
+
+
+static int frame_on_canvas = 0;
+
+
+static void leave_canvas(void)
+{
+	if (frame_on_canvas)
+		canvas_frame_end();
+	frame_on_canvas = 0;
+}
+
+
 /* ----- drag frame labels ------------------------------------------------- */
 
 
+#if 0
+
+/*
+ * Setting our own icon looks nice but it slows things down to the point where
+ * cursor movements can lag noticeable and it adds yet another element to an
+ * already crowded cursor.
+ */
+
+static void drag_frame_begin(GtkWidget *widget,
+    GtkTextDirection previous_direction, gpointer user_data)
+{
+	GdkPixmap *pixmap;
+	GdkBitmap *mask;
+	GdkColormap *cmap;
+
+	pixmap = gdk_pixmap_create_from_xpm_d(DA, &mask, NULL, xpm_frame);
+	cmap = gdk_drawable_get_colormap(root->window);
+	gtk_drag_source_set_icon(widget, cmap, pixmap, mask);
+	g_object_unref(pixmap);
+	g_object_unref(mask);
+
+	dragging = user_data;
+}
+
+#endif
+
+
 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;
+	/* nothing else to do yet */
+	return FALSE;
 }
 
 
+static void drag_frame_end(GtkWidget *widget, GdkDragContext *drag_context,
+    gpointer user_data)
+{
+	leave_canvas();
+	drag_end(widget, drag_context, user_data);
+}
+
+
 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);
+	    &target_frame, 1, GDK_ACTION_COPY);
 	setup_drag_common(box, frame);
+
+	/* override */
+#if 0
+	g_signal_connect(G_OBJECT(box), "drag-begin",
+	    G_CALLBACK(drag_frame_begin), frame);
+#endif
+	g_signal_connect(G_OBJECT(box), "drag-end",
+	    G_CALLBACK(drag_frame_end), frame);
+
 	g_signal_connect(G_OBJECT(box), "drag-motion",
 	    G_CALLBACK(drag_frame_motion), frame);
 }
@@ -386,16 +456,52 @@
 {
 	if (!has_target(widget, drag_context, "frame"))
 		return FALSE;
-//fprintf(stderr, "canvas\n");
+gtk_drag_finish(drag_context, FALSE, FALSE, time_);
 return FALSE;
+	if (!frame_on_canvas) {
+		frame_on_canvas = 1;
+		canvas_frame_begin(dragging);
+	}
+	if (canvas_frame_motion(dragging, x, y)) {
+		gdk_drag_status(drag_context, GDK_ACTION_COPY, time_);
+		return TRUE;
+	} else {
+		gdk_drag_status(drag_context, 0, time_);
+		return FALSE;
+	}
 }
 
 
+static void drag_canvas_leave(GtkWidget *widget, GdkDragContext *drag_context,
+    guint time_, gpointer user_data)
+{
+	leave_canvas();
+}
+
+
+static gboolean drag_canvas_drop(GtkWidget *widget,
+    GdkDragContext *drag_context, gint x, gint y, guint time_,
+    gpointer user_data)
+{
+	if (!has_target(widget, drag_context, "frame"))
+		return FALSE;
+	if (!canvas_frame_drop(dragging, x, y))
+		return FALSE;
+	gtk_drag_finish(drag_context, TRUE, FALSE, time_);
+	return TRUE;
+}
+
+
 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);
+	gtk_drag_dest_set(canvas,
+	    GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+	    &target_frame, 1, GDK_ACTION_COPY);
+
 	g_signal_connect(G_OBJECT(canvas), "drag-motion",
 	    G_CALLBACK(drag_canvas_motion), NULL);
+	g_signal_connect(G_OBJECT(canvas), "drag-leave",
+	    G_CALLBACK(drag_canvas_leave), NULL);
+	g_signal_connect(G_OBJECT(canvas), "drag-drop",
+	    G_CALLBACK(drag_canvas_drop), NULL);
 }

Modified: trunk/eda/fped/gui_frame_drag.h
===================================================================
--- trunk/eda/fped/gui_frame_drag.h	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_frame_drag.h	2010-04-24 21:46:43 UTC (rev 5932)
@@ -20,6 +20,7 @@
 
 
 int is_dragging(void *this);
+int is_dragging_anything(void);
 
 void setup_var_drag(struct var *var);
 void setup_value_drag(struct value *value);

Modified: trunk/eda/fped/gui_tool.c
===================================================================
--- trunk/eda/fped/gui_tool.c	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_tool.c	2010-04-24 21:46:43 UTC (rev 5932)
@@ -803,7 +803,7 @@
 }
 
 
-void tool_hover(struct coord pos)
+int tool_hover(struct coord pos)
 {
 	struct inst *curr;
 
@@ -825,18 +825,87 @@
 #endif
 
 	if (curr == hover_inst)
-		return;
+		return !!curr;
 	if (hover_inst) {
 		over_leave();
 		hover_inst = NULL;
 	}
 	if (!curr)
-		return;
+		return 0;
 	hover_inst = curr;
 	over_enter(hover_save_and_draw, NULL);
+	return 1;
 }
 
 
+/* ----- frame drag and drop ----------------------------------------------- */
+
+
+/*
+ * When dragging a frame, we temporarily replace the selected tool (if any)
+ * with the frame tool.
+ */
+
+
+static struct tool_ops *pushed_ops;
+
+
+void tool_push_frame(struct frame *frame)
+{
+	pushed_ops = active_ops;
+	locked_frame = frame;
+	active_ops = &frame_ops;
+	/*
+	 * We don't need to call tool_selected since, with drag and drop, the
+	 * frame tools doesn't need activation anymore.
+	 */
+}
+
+
+static int do_place_frame(struct frame *frame, struct coord pos)
+{
+	if (!get_hover_inst(pos))
+		return 0;
+	tool_consider_drag(pos);
+	return 1;
+}
+
+
+/*
+ * Gtk calls drag-leave, drag-end, and only then drag-drop. So we'll already
+ * have cleaned up in tool_pop_frame before we get here. In order to place the
+ * frame, we need to activate the frame tool again.
+ *
+ * @@@ bug: there's a tool_reset in this path, so we'll lose the widget of the
+ * tool that's really active. This problem will vanish when scrapping the
+ * old-style frame referenes.
+ */
+
+int tool_place_frame(struct frame *frame, struct coord pos)
+{
+	int ok;
+
+	active_ops = &frame_ops;
+	ok = do_place_frame(frame, pos);
+	active_ops = pushed_ops;
+	return ok;
+}
+
+
+void tool_pop_frame(void)
+{
+	if (!active_tool)
+		return;
+	active_ops = pushed_ops;
+	/*
+	 * We don't need to call tool_selected since the only tool that could
+	 * use this would be the delete tool, and there the semantics would be
+	 * undesirable. Also, the delete tool never stays active, so it can't
+	 * appear together with drag and drop anyway.
+	 */
+}
+
+
 /* ----- tooltip ----------------------------------------------------------- */
 
 

Modified: trunk/eda/fped/gui_tool.h
===================================================================
--- trunk/eda/fped/gui_tool.h	2010-04-24 09:54:32 UTC (rev 5931)
+++ trunk/eda/fped/gui_tool.h	2010-04-24 21:46:43 UTC (rev 5932)
@@ -46,7 +46,7 @@
 void do_move_to_arc(struct inst *inst, struct inst *to, int i);
 
 void tool_dehover(void);
-void tool_hover(struct coord pos);
+int tool_hover(struct coord pos);
 const char *tool_tip(struct coord pos);
 int tool_consider_drag(struct coord pos);
 void tool_drag(struct coord to);
@@ -73,6 +73,10 @@
 void tool_frame_update(void);
 void tool_frame_deleted(const struct frame *frame);
 
+void tool_push_frame(struct frame *frame);
+int tool_place_frame(struct frame *frame, struct coord pos);
+void tool_pop_frame(void);
+
 void tool_selected_inst(struct inst *inst);
 
 GtkWidget *get_icon_by_inst(const struct inst *inst);




More information about the commitlog mailing list