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