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



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5932 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2010-04-24 21:46:43 +00:00
parent a4d2926b2d
commit 0b241a14fe
6 changed files with 240 additions and 17 deletions

View File

@ -187,6 +187,41 @@ static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
}
/* ----- 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 @@ static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event,
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 expose_event(GtkWidget *widget, GdkEventExpose *event,
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 @@ static gboolean leave_notify_event(GtkWidget *widget, GdkEventCrossing *event,
tool_cancel_drag();
tool_dehover();
dragging = 0;
return TRUE;
return FALSE;
}

View File

@ -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_out_center(void);
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);

View File

@ -15,8 +15,14 @@
#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,
@ -61,6 +67,12 @@ int is_dragging(void *this)
}
int is_dragging_anything(void)
{
return !!dragging;
}
/* ----- helper functions for indexed list and swapping -------------------- */
@ -273,7 +285,7 @@ void setup_var_drag(struct var *var)
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 @@ void setup_value_drag(struct value *value)
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,17 +362,66 @@ void setup_value_drag(struct value *value)
}
/* ----- 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);
}
@ -370,8 +431,17 @@ void setup_frame_drag(struct frame *frame)
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 @@ static gboolean drag_canvas_motion(GtkWidget *widget,
{
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);
}

View File

@ -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);

View File

@ -803,7 +803,7 @@ static struct inst *get_hover_inst(struct coord pos)
}
void tool_hover(struct coord pos)
int tool_hover(struct coord pos)
{
struct inst *curr;
@ -825,15 +825,84 @@ got:
#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.
*/
}

View File

@ -46,7 +46,7 @@ struct pix_buf *gui_hover_frame(struct inst *self);
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 @@ struct pix_buf *drag_new_line(struct inst *from, struct coord to);
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);