mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-25 18:55: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:
parent
093a34f860
commit
a4d2926b2d
@ -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;
|
||||
|
91
gui_frame.c
91
gui_frame.c
@ -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:
|
||||
if (is_dragging(var))
|
||||
return FALSE;
|
||||
edit_var(var, set_col_values, var, -1);
|
||||
return FALSE;
|
||||
case 3:
|
||||
pop_up_table_var(var, event);
|
||||
break;
|
||||
return TRUE;
|
||||
}
|
||||
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,12 +948,9 @@ 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 TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -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,12 +1716,9 @@ static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event,
|
||||
edit_frame(frame);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pop_up_frame(frame, event);
|
||||
break;
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
158
gui_frame_drag.c
158
gui_frame_drag.c
@ -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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user