From 30664583a1ba7caa07c45121ac359d0ad61ca73e Mon Sep 17 00:00:00 2001 From: werner Date: Thu, 6 Aug 2009 20:19:00 +0000 Subject: [PATCH] - when dragging the endpoint of an arc, show a helper line to visually connect the point being dragged - added pop-up menus for all frame and variable items (on-going) - clickable items in the frame/var area now only respond to the left button, unless they have a pop-up - removed the frame delete icon - use pop-up instead git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5396 99fdad57-331a-0410-800a-d7fa5415bdb3 --- delete.c | 25 +++ delete.h | 4 + fpd.y | 3 + gui.c | 571 +++++++++++++++++++++++++++++++++++++++++++++------- gui_tools.c | 19 +- obj.h | 1 + 6 files changed, 544 insertions(+), 79 deletions(-) diff --git a/delete.c b/delete.c index f114c93..d4c0b3a 100644 --- a/delete.c +++ b/delete.c @@ -225,6 +225,31 @@ static void undelete_obj(struct obj *obj, struct obj *prev) } } +/* ----- tables ------------------------------------------------------------ */ + + +void delete_row(struct row *row) +{ +} + + +void delete_column(struct table *table, int n) +{ +} + + +void delete_table(struct table *table) +{ +} + + +/* ----- loops ------------------------------------------------------------- */ + + +void delete_loop(struct loop *loop) +{ +} + /* ----- frames ------------------------------------------------------------ */ diff --git a/delete.h b/delete.h index b09a54c..5257990 100644 --- a/delete.h +++ b/delete.h @@ -20,6 +20,10 @@ void delete_vec(struct vec *vec); void delete_obj(struct obj *obj); +void delete_row(struct row *row); +void delete_column(struct table *table, int n); +void delete_table(struct table *table); +void delete_loop(struct loop *loop); void delete_frame(struct frame *frame); int destroy(void); int undelete(void); diff --git a/fpd.y b/fpd.y index 4a7db2e..1a6094a 100644 --- a/fpd.y +++ b/fpd.y @@ -78,6 +78,7 @@ static void make_var(const char *id, struct expr *expr) table->vars = zalloc_type(struct var); table->vars->name = id; table->vars->frame = curr_frame; + table->vars->table = table; table->rows = zalloc_type(struct row); table->rows->table = table; table->rows->values = zalloc_type(struct value); @@ -97,6 +98,7 @@ static void make_loop(const char *id, struct expr *from, struct expr *to) loop->var.name = id; loop->var.next = NULL; loop->var.frame = curr_frame; + loop->var.table = NULL; loop->from.expr = from; loop->from.row = NULL; loop->from.next = NULL; @@ -296,6 +298,7 @@ var: $$ = zalloc_type(struct var); $$->name = $1; $$->frame = curr_frame; + $$->table = curr_table; $$->next = NULL; n_vars++; } diff --git a/gui.c b/gui.c index 3725faf..64a2d93 100644 --- a/gui.c +++ b/gui.c @@ -37,6 +37,406 @@ GtkWidget *root; static GtkWidget *frames_box; +/* ----- popup dispatcher -------------------------------------------------- */ + + +static void *popup_data; + + +static void pop_up(GtkWidget *menu, GdkEventButton *event, void *data) +{ + popup_data = data; + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, + event->button, event->time); +} + + +/* ----- popup: frame ------------------------------------------------------ */ + + +static GtkItemFactory *factory_frame; +static GtkWidget *popup_frame_widget; + + +static void select_frame(struct frame *frame); + + +static void popup_add_frame(void) +{ + struct frame *parent = popup_data; + struct frame *new; + + new = zalloc_type(struct frame); + new->name = unique("_"); + new->next = parent; + new->prev = parent->prev; + if (parent->prev) + parent->prev->next = new; + else + frames = new; + parent->prev = new; + change_world(); +} + + +static void popup_del_frame(void) +{ + struct frame *frame = popup_data; + + assert(frame != root_frame); + delete_frame(frame); + if (active_frame == frame) + select_frame(root_frame); + change_world(); +} + + +/* @@@ merge with fpd.y */ + +static void popup_add_table(void) +{ + struct frame *frame = popup_data; + struct table *table, **walk; + + table = zalloc_type(struct table); + table->vars = zalloc_type(struct var); + table->vars->name = unique("_"); + table->vars->frame = frame; + table->vars->table = table; + table->rows = zalloc_type(struct row); + table->rows->table = table; + table->rows->values = zalloc_type(struct value); + table->rows->values->expr = parse_expr("0"); + table->rows->values->row = table->rows; + table->active_row = table->rows; + for (walk = &frame->tables; *walk; walk = &(*walk)->next); + *walk = table; + change_world(); +} + + +static void popup_add_loop(void) +{ + struct frame *frame = popup_data; + struct loop *loop, **walk; + + loop = zalloc_type(struct loop); + loop->var.name = unique("_"); + loop->var.frame = frame; + loop->from.expr = parse_expr("0"); + loop->to.expr = parse_expr("0"); + loop->next = NULL; + for (walk = &frame->loops; *walk; walk = &(*walk)->next); + *walk = loop; + change_world(); +} + + +static GtkItemFactoryEntry popup_frame_entries[] = { + { "/Add frame", NULL, popup_add_frame, 0, "" }, + { "/sep0", NULL, NULL, 0, "" }, + { "/Add variable", NULL, popup_add_table, 0, "" }, + { "/Add loop", NULL, popup_add_loop, 0, "" }, + { "/sep1", NULL, NULL, 0, "" }, + { "/Delete frame", NULL, popup_del_frame, 0, "" }, + { "/sep2", NULL, NULL, 0, "" }, + { "/Close", NULL, NULL, 0, "" }, + { NULL } +}; + + +static void pop_up_frame(struct frame *frame, GdkEventButton *event) +{ + gtk_widget_set_sensitive( + gtk_item_factory_get_item(factory_frame, "/Delete frame"), + frame != root_frame); + pop_up(popup_frame_widget, event, frame); +} + + +/* ----- popup: single variable -------------------------------------------- */ + + +static GtkItemFactory *factory_single_var; +static GtkWidget *popup_single_var_widget; + + + +static void add_row_here(struct table *table, struct row **anchor) +{ + struct row *row; + const struct value *walk; + struct value *value; + + row = zalloc_type(struct row); + row->table = table; + /* @@@ future: adjust type */ + for (walk = table->rows->values; walk; walk = walk->next) { + value = zalloc_type(struct value); + value->expr = parse_expr("0"); + value->row = row; + value->next = row->values; + row->values = value; + } + row->next = *anchor; + *anchor = row; + change_world(); +} + + +static void add_column_here(struct table *table, struct var **anchor) +{ + const struct var *walk; + struct var *var; + struct row *row; + struct value *value; + struct value **value_anchor; + int n = 0, i; + + for (walk = table->vars; walk != *anchor; walk = walk->next) + n++; + var = zalloc_type(struct var); + var->name = unique("_"); + var->frame = table->vars->frame; + var->table = table; + var->next = *anchor; + *anchor = var; + for (row = table->rows; row; row = row->next) { + value_anchor = &row->values; + for (i = 0; i != n; i++) + value_anchor = &(*value_anchor)->next; + value = zalloc_type(struct value); + value->expr = parse_expr("0"); + value->row = row; + value->next = *value_anchor; + *value_anchor = value; + } + change_world(); +} + + +static void popup_add_row(void) +{ + struct var *var = popup_data; + + add_row_here(var->table, &var->table->rows); +} + + +static void popup_add_column(void) +{ + struct var *var = popup_data; + + add_column_here(var->table, &var->next); +} + + +static void popup_del_table(void) +{ + struct var *var = popup_data; + + delete_table(var->table); + change_world(); +} + + +static GtkItemFactoryEntry popup_single_var_entries[] = { + { "/Add row", NULL, popup_add_row, 0, "" }, + { "/Add column", NULL, popup_add_column, 0, "" }, + { "/sep1", NULL, NULL, 0, "" }, + { "/Delete variable", NULL, popup_del_table, 0, "" }, + { "/sep2", NULL, NULL, 0, "" }, + { "/Close", NULL, NULL, 0, "" }, + { NULL } +}; + + +static void pop_up_single_var(struct var *var, GdkEventButton *event) +{ + pop_up(popup_single_var_widget, event, var); +} + + +/* ----- popup: table variable --------------------------------------------- */ + + +static GtkItemFactory *factory_table_var; +static GtkWidget *popup_table_var_widget; + + +static void popup_del_column(void) +{ + struct var *var = popup_data; + const struct var *walk; + int n = 0; + + for (walk = var->table->vars; walk != var; walk = walk->next) + n++; + delete_column(var->table, n); + change_world(); +} + + +static GtkItemFactoryEntry popup_table_var_entries[] = { + { "/Add row", NULL, popup_add_row, 0, "" }, + { "/Add column", NULL, popup_add_column, 0, "" }, + { "/sep1", NULL, NULL, 0, "" }, + { "/Delete table", NULL, popup_del_table, 0, "" }, + { "/Delete column", NULL, popup_del_column, 0, "" }, + { "/sep2", NULL, NULL, 0, "" }, + { "/Close", NULL, NULL, 0, "" }, + { NULL } +}; + + +static void pop_up_table_var(struct var *var, GdkEventButton *event) +{ + gtk_widget_set_sensitive( + gtk_item_factory_get_item(factory_table_var, "/Delete column"), + var->table->vars->next != NULL); + pop_up(popup_table_var_widget, event, var); +} + + +/* ----- popup: table value ------------------------------------------------ */ + + +static GtkItemFactory *factory_table_value; +static GtkWidget *popup_table_value_widget; + + +static void popup_add_column_by_value(void) +{ + struct value *value = popup_data; + const struct value *walk; + struct table *table = value->row->table; + struct var *var = table->vars; + + for (walk = value->row->values; walk != value; walk = walk->next) + var = var->next; + add_column_here(table, &var->next); +} + + +static void popup_add_row_by_value(void) +{ + struct value *value = popup_data; + + add_row_here(value->row->table, &value->row->next); +} + + +static void popup_del_row(void) +{ + struct value *value = popup_data; + + delete_row(value->row); + change_world(); +} + + +static void popup_del_column_by_value(void) +{ + struct value *value = popup_data; + const struct value *walk; + int n = 0; + + for (walk = value->row->values; walk != value; walk = walk->next); + delete_column(value->row->table, n); + change_world(); +} + + +static GtkItemFactoryEntry popup_table_value_entries[] = { + { "/Add row", NULL, popup_add_row_by_value, 0, "" }, + { "/Add column", NULL, popup_add_column_by_value, + 0, "" }, + { "/sep1", NULL, NULL, 0, "" }, + { "/Delete row", NULL, popup_del_row, 0, "" }, + { "/Delete column", NULL, popup_del_column_by_value, + 0, "" }, + { "/sep2", NULL, NULL, 0, "" }, + { "/Close", NULL, NULL, 0, "" }, + { NULL } +}; + + +static void pop_up_table_value(struct value *value, GdkEventButton *event) +{ + gtk_widget_set_sensitive( + gtk_item_factory_get_item(factory_table_value, "/Delete row"), + value->row->table->rows->next != NULL); + gtk_widget_set_sensitive( + gtk_item_factory_get_item(factory_table_value, "/Delete column"), + value->row->table->vars->next != NULL); + pop_up(popup_table_value_widget, event, value); +} + + +/* ----- popup: loop ------------------------------------------------------- */ + + +static GtkItemFactory *factory_loop_var; +static GtkWidget *popup_loop_var_widget; + + +static void popup_del_loop(void) +{ + struct loop *loop = popup_data; + + delete_loop(loop); + change_world(); +} + + +static GtkItemFactoryEntry popup_loop_var_entries[] = { + { "/Delete loop", NULL, popup_del_loop, 0, "" }, + { "/sep2", NULL, NULL, 0, "" }, + { "/Close", NULL, NULL, 0, "" }, + { NULL } +}; + + +static void pop_up_loop_var(struct loop *loop, GdkEventButton *event) +{ + pop_up(popup_loop_var_widget, event, loop); +} + + +/* ----- make popups ------------------------------------------------------- */ + + +static GtkWidget *make_popup(const char *name, GtkItemFactory **factory, + GtkItemFactoryEntry *entries) +{ + GtkWidget *popup; + int n; + + n = 0; + for (n = 0; entries[n].path; n++); + + *factory = gtk_item_factory_new(GTK_TYPE_MENU, name, NULL); + gtk_item_factory_create_items(*factory, n, entries, NULL); + popup = gtk_item_factory_get_widget(*factory, name); + return popup; +} + + +static void make_popups(void) +{ + popup_frame_widget = make_popup("", + &factory_frame, popup_frame_entries); + popup_single_var_widget = make_popup("", + &factory_single_var, popup_single_var_entries); + popup_table_var_widget = make_popup("", + &factory_table_var, popup_table_var_entries); + popup_table_value_widget = make_popup("", + &factory_table_value, popup_table_value_entries); + popup_loop_var_widget = make_popup("", + &factory_loop_var, popup_loop_var_entries); +} + + /* ----- menu bar ---------------------------------------------------------- */ @@ -188,7 +588,16 @@ static GtkWidget *add_activator(GtkWidget *hbox, int active, static gboolean assignment_var_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - edit_var(data); + struct var *var = data; + + switch (event->button) { + case 1: + edit_var(var); + break; + case 3: + pop_up_single_var(var, event); + break; + } return TRUE; } @@ -196,7 +605,13 @@ static gboolean assignment_var_select_event(GtkWidget *widget, static gboolean assignment_value_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - edit_value(data); + struct value *value = data; + + switch (event->button) { + case 1: + edit_value(value); + break; + } return TRUE; } @@ -257,7 +672,16 @@ static void select_row(struct row *row) static gboolean table_var_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - edit_var(data); + struct var *var = data; + + switch (event->button) { + case 1: + edit_var(var); + break; + case 3: + pop_up_table_var(var, event); + break; + } return TRUE; } @@ -267,11 +691,18 @@ static gboolean table_value_select_event(GtkWidget *widget, { struct value *value = data; - if (!value->row || value->row->table->active_row == value->row) - edit_value(value); - else { - select_row(value->row); - change_world(); + switch (event->button) { + case 1: + if (!value->row || value->row->table->active_row == value->row) + edit_value(value); + else { + select_row(value->row); + change_world(); + } + break; + case 3: + pop_up_table_value(value, event); + break; } return TRUE; } @@ -353,7 +784,14 @@ static gboolean loop_var_select_event(GtkWidget *widget, { struct loop *loop = data; - edit_var(&loop->var); + switch (event->button) { + case 1: + edit_var(&loop->var); + break; + case 3: + pop_up_loop_var(loop, event); + break; + } return TRUE; } @@ -363,7 +801,11 @@ static gboolean loop_from_select_event(GtkWidget *widget, { struct loop *loop = data; - edit_value(&loop->from); + switch (event->button) { + case 1: + edit_value(&loop->from); + break; + } return TRUE; } @@ -373,7 +815,11 @@ static gboolean loop_to_select_event(GtkWidget *widget, { struct loop *loop = data; - edit_value(&loop->to); + switch (event->button) { + case 1: + edit_value(&loop->to); + break; + } return TRUE; } @@ -383,8 +829,13 @@ static gboolean loop_select_event(GtkWidget *widget, GdkEventButton *event, { struct loop *loop = data; - loop->active = (long) gtk_object_get_data(GTK_OBJECT(widget), "value"); - change_world(); + switch (event->button) { + case 1: + loop->active = + (long) gtk_object_get_data(GTK_OBJECT(widget), "value"); + change_world(); + break; + } return TRUE; } @@ -495,11 +946,15 @@ static void unselect_part_name(void *data) static gboolean part_name_edit_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - inst_select_outside(widget, unselect_part_name); - label_in_box_bg(widget, COLOR_PART_NAME_EDITING); - status_set_type_entry("part ="); - status_set_name("%s", part_name); - edit_name(&part_name, validate_part_name, NULL); + switch (event->button) { + case 1: + inst_select_outside(widget, unselect_part_name); + label_in_box_bg(widget, COLOR_PART_NAME_EDITING); + status_set_type_entry("part ="); + status_set_name("%s", part_name); + edit_name(&part_name, validate_part_name, NULL); + break; + } return TRUE; } @@ -575,11 +1030,20 @@ static void select_frame(struct frame *frame) static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - if (active_frame != data) - select_frame(data); - else { - if (active_frame->name) - edit_frame(data); + struct frame *frame = data; + + switch (event->button) { + case 1: + if (active_frame != frame) + select_frame(frame); + else { + if (active_frame->name) + edit_frame(frame); + } + break; + case 3: + pop_up_frame(frame, event); + break; } return TRUE; } @@ -604,52 +1068,6 @@ static GtkWidget *build_frame_label(struct frame *frame) } -/* ----- frame delete ------------------------------------------------------ */ - - -static gboolean frame_delete_event(GtkWidget *widget, GdkEventButton *event, - gpointer data) -{ - struct frame *frame = data; - - switch (event->button) { - case 1: - if (frame == root_frame) { - fail("you cannot delete the root frame"); - break; - } - delete_frame(frame); - if (active_frame == frame) - select_frame(root_frame); - change_world(); - break; - } - return TRUE; -} - - -static GtkWidget *build_frame_delete(struct frame *frame) -{ - GtkWidget *evbox, *image; - GtkWidget *align; - - evbox = gtk_event_box_new(); - image = - gtk_image_new_from_stock(GTK_STOCK_CANCEL, - GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_container_add(GTK_CONTAINER(evbox), image); - - align = gtk_alignment_new(0.3, 0, 0, 0); - gtk_container_add(GTK_CONTAINER(align), evbox); - gtk_alignment_set_padding(GTK_ALIGNMENT(align), 2, 0, 0, 0); - - g_signal_connect(G_OBJECT(evbox), - "button_press_event", G_CALLBACK(frame_delete_event), frame); - - return align; -} - - /* ----- frame references -------------------------------------------------- */ @@ -658,8 +1076,12 @@ static gboolean frame_ref_select_event(GtkWidget *widget, GdkEventButton *event, { struct obj *obj = data; - obj->u.frame.ref->active_ref = data; - change_world(); + switch (event->button) { + case 1: + obj->u.frame.ref->active_ref = data; + change_world(); + break; + } return TRUE; } @@ -686,7 +1108,7 @@ static GtkWidget *build_frame_refs(const struct frame *frame) static void build_frames(GtkWidget *vbox) { struct frame *frame; - GtkWidget *tab, *label, *delete, *refs, *vars; + GtkWidget *tab, *label, *refs, *vars; int n = 0; destroy_all_children(GTK_CONTAINER(vbox)); @@ -707,10 +1129,6 @@ static void build_frames(GtkWidget *vbox) gtk_table_attach_defaults(GTK_TABLE(tab), label, 0, 1, n*2+1, n*2+2); - delete = build_frame_delete(frame); - gtk_table_attach_defaults(GTK_TABLE(tab), delete, - 0, 1, n*2+2, n*2+3); - refs = build_frame_refs(frame); gtk_table_attach_defaults(GTK_TABLE(tab), refs, 1, 2, n*2+1, n*2+2); @@ -818,6 +1236,7 @@ int gui_main(void) init_canvas(); edit_nothing(); select_frame(root_frame); + make_popups(); gtk_main(); diff --git a/gui_tools.c b/gui_tools.c index d175e26..0910568 100644 --- a/gui_tools.c +++ b/gui_tools.c @@ -386,8 +386,8 @@ static int end_new_circ(struct draw_ctx *ctx, struct pix_buf *draw_move_arc(struct inst *inst, struct draw_ctx *ctx, struct coord pos, int i) { - struct coord c, from, to; - double r, a1, a2; + struct coord c, from, to, end; + double r, r_save, a1, a2; struct pix_buf *buf; c = translate(ctx, inst->base); @@ -420,8 +420,21 @@ struct pix_buf *draw_move_arc(struct inst *inst, struct draw_ctx *ctx, a2 = -theta(c, to); if (a2 < a1) a2 += 360.0; - buf = save_pix_buf(DA, c.x-r, c.y-r, c.x+r, c.y+r, 1); + + if (i != 2) + r_save = r; + else { + r_save = hypot(to.x-c.x, to.y-c.y); + if (r > r_save) + r_save = r; + } + buf = save_pix_buf(DA, + c.x-r_save, c.y-r_save, c.x+r_save, c.y+r_save, 1); draw_arc(DA, gc_drag, FALSE, c.x, c.y, r, a1, a2); + if (i == 2) { + end = rotate_r(c, r_save, -a2); + gdk_draw_line(DA, gc_drag, c.x, c.y, end.x, end.y); + } return buf; } diff --git a/obj.h b/obj.h index 2f4a997..0f1944e 100644 --- a/obj.h +++ b/obj.h @@ -27,6 +27,7 @@ struct var { /* back reference */ struct frame *frame; + struct table *table; /* NULL if loop */ /* for the GUI */ GtkWidget *widget;