1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-11-05 04:35:19 +02:00

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



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5930 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2010-04-23 22:01:56 +00:00
parent 093a34f860
commit a4d2926b2d
4 changed files with 217 additions and 41 deletions

View File

@ -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 @@ static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event,
if (event->state & GDK_BUTTON2_MASK)
drag_middle(pos);
update_pos(pos);
return TRUE;
return FALSE;
}
@ -541,6 +542,8 @@ GtkWidget *make_canvas(void)
gtk_widget_set_double_buffered(canvas, FALSE);
setup_canvas_drag(canvas);
draw_ctx.widget = canvas;
return canvas;

View File

@ -886,30 +886,59 @@ static void set_row_values(void *user, const struct value *values,
}
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:
edit_var(var, set_col_values, var, -1);
if (is_dragging(var))
return FALSE;
case 3:
pop_up_table_var(var, event);
break;
}
edit_var(var, set_col_values, var, -1);
return TRUE;
}
return FALSE;
}
static gboolean table_value_select_event(GtkWidget *widget,
static gboolean table_value_press_event(GtkWidget *widget,
GdkEventButton *event, gpointer data)
{
struct value *value = data;
switch (event->button) {
case 3:
pop_up_table_value(value, event);
return TRUE;
}
return FALSE;
}
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,13 +948,10 @@ static gboolean table_value_select_event(GtkWidget *widget,
select_row(value->row);
change_world();
}
return FALSE;
case 3:
pop_up_table_value(value, event);
break;
}
return TRUE;
}
return FALSE;
}
static gboolean table_scroll_event(GtkWidget *widget, GdkEventScroll *event,
@ -1009,7 +1035,10 @@ static void build_table(GtkWidget *vbox, struct frame *frame,
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);
@ -1034,7 +1063,10 @@ static void build_table(GtkWidget *vbox, struct frame *frame,
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);
@ -1653,13 +1685,29 @@ void select_frame(struct frame *frame)
}
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,13 +1716,10 @@ static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event,
edit_frame(frame);
}
}
break;
case 3:
pop_up_frame(frame, event);
break;
}
return TRUE;
}
return FALSE;
}
static GtkWidget *build_frame_label(struct frame *frame)
@ -1691,9 +1736,13 @@ static GtkWidget *build_frame_label(struct frame *frame)
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);
}

View File

@ -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,7 +185,27 @@ static void swap_rows(struct row **a, struct row **b)
}
/* ----- 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,
@ -163,11 +220,28 @@ static void drag_begin(GtkWidget *widget,
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 @@ static gboolean drag_var_motion(GtkWidget *widget,
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 @@ static gboolean drag_var_motion(GtkWidget *widget,
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 @@ static gboolean drag_value_motion(GtkWidget *widget,
{
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 @@ static gboolean drag_value_motion(GtkWidget *widget,
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);
}

View File

@ -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 */