diff --git a/README b/README index 7075423..b042b20 100644 --- a/README +++ b/README @@ -10,6 +10,28 @@ the textual definition also has a straightforward equivalent operation that can be performed through the GUI. +Building +-------- + +Check out the repository: + + svn co http://svn.openmoko.org/trunk/eda/fped + cd fped + +Get updates: + + svn update + +Compile: + + make dep + make + +Run an example: + + ./fped qfp.fpd + + Motivation ---------- @@ -346,7 +368,8 @@ Parentheses can be used to change precedence. GUI --- -Keys: +Keyboard shortcuts +- - - - - - - - - Space reset user coordinates +, = zoom in (like mouse wheel forward) @@ -356,3 +379,28 @@ Space reset user coordinates # zoom and center to currently active frame instance Delete delete the currently selected object U undelete the previously deleted object + + +Canvas +- - - + +To create a new object, click on the corresponding tool icon, move the +mouse to the base point of the new object, then drag to the object's +second point. + +Frame references are created as follows: + +- select the frame you want to add +- click on the frame icon. A black dot should appear on the icon. +- select the frame on which you want to add the new reference. + The black dot should change to a green dot. If the current frame + is a child of the selected frame, the dot remains black. +- click on the desired base location + +To change a point of an object, select the object, then drag the point +to its new location. To edit the object's parameters, select it and +make the changes in the input area at the bottom. + +To delete an object, select it and press Delete. Deleted objects can +be undeleted by pressing "u". If any other changes have been made +since deletion, fped may misbehave. diff --git a/TODO b/TODO index 18ba2be..4c87ebc 100644 --- a/TODO +++ b/TODO @@ -17,6 +17,7 @@ Style: - make column of entry field greedily consume all unallocated space - status area looks awful - status area bounces when something becomes editable +- add button with GTK_STOCK_UNDELETE for "undelete" to menu bar Bugs: - default silk width has no business being hard-coded in obj.c diff --git a/delete.c b/delete.c index 4c8b93b..92205f4 100644 --- a/delete.c +++ b/delete.c @@ -25,8 +25,13 @@ static struct deletion { enum del_type { dt_vec, dt_obj, + dt_frame, } type; union { + struct { + struct frame *ref; + struct frame *prev; + } frame; struct { struct vec *ref; struct vec *prev; @@ -77,7 +82,7 @@ static void rereference_vec(struct vec *vec) } -int delete_vec(struct vec *vec) +void delete_vec(struct vec *vec) { struct vec *walk, *prev; struct deletion *del; @@ -85,7 +90,7 @@ int delete_vec(struct vec *vec) if (vec->n_refs) { fail("vector has %d reference%s", vec->n_refs, vec->n_refs == 1 ? "" : "s"); - return 0; + return; } prev = NULL; for (walk = vec->frame->vecs; walk != vec; walk = walk->next) @@ -98,7 +103,6 @@ int delete_vec(struct vec *vec) del = new_deletion(dt_vec); del->u.vec.ref = vec; del->u.vec.prev = prev; - return 1; } @@ -204,7 +208,7 @@ static void rereference_obj(struct obj *obj) } -int delete_obj(struct obj *obj) +void delete_obj(struct obj *obj) { struct obj *walk, *prev; struct deletion *del; @@ -220,7 +224,6 @@ int delete_obj(struct obj *obj) del = new_deletion(dt_obj); del->u.obj.ref = obj; del->u.obj.prev = prev; - return 1; } @@ -237,6 +240,54 @@ static void undelete_obj(struct obj *obj, struct obj *prev) } +/* ----- frames ------------------------------------------------------------ */ + + +static void delete_references(const struct frame *ref) +{ + struct frame *frame; + struct obj *obj; + + for (frame = frames; frame; frame = frame->next) + for (obj = frame->objs; obj; obj = obj->next) + if (obj->type == ot_frame) + if (obj->u.frame.ref == ref) + delete_obj(obj); +} + + +void delete_frame(struct frame *frame) +{ + struct deletion *del; + + delete_references(frame); + + del = new_deletion(dt_frame); + del->u.frame.ref = frame; + del->u.frame.prev = frame->prev; + + if (frame->next) + frame->next->prev = frame->prev; + if (frame->prev) + frame->prev->next = frame->next; + else + frames = frame->next; +} + + +static void undelete_frame(struct frame *frame, struct frame *prev) +{ + if (prev) { + assert(frame->next == prev->next); + prev->next = frame; + } else { + assert(frame->next == frames); + frames = frame; + } + frame->next->prev = frame; +} + + /* ----- destroy/undelete interface ---------------------------------------- */ @@ -254,6 +305,10 @@ int destroy(void) case dt_obj: destroy_obj(del->u.obj.ref); break; + case dt_frame: + abort(); + /* @@@ later */ + break; default: abort(); } @@ -277,6 +332,9 @@ int undelete(void) case dt_obj: undelete_obj(del->u.obj.ref, del->u.obj.prev); break; + case dt_frame: + undelete_frame(del->u.frame.ref, del->u.frame.prev); + break; default: abort(); } diff --git a/delete.h b/delete.h index 85495f7..b09a54c 100644 --- a/delete.h +++ b/delete.h @@ -18,8 +18,9 @@ #include "obj.h" -int delete_vec(struct vec *vec); -int delete_obj(struct obj *obj); +void delete_vec(struct vec *vec); +void delete_obj(struct obj *obj); +void delete_frame(struct frame *frame); int destroy(void); int undelete(void); diff --git a/gui.c b/gui.c index d7480de..d8a4340 100644 --- a/gui.c +++ b/gui.c @@ -15,10 +15,13 @@ #include #include #include +#include #include "util.h" +#include "error.h" #include "inst.h" #include "obj.h" +#include "delete.h" #include "unparse.h" #include "gui_util.h" #include "gui_style.h" @@ -540,6 +543,49 @@ 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; + + 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); + + gtk_misc_set_padding(GTK_MISC(image), 2, 2); + gtk_misc_set_alignment(GTK_MISC(image), 0.3, 0); + + g_signal_connect(G_OBJECT(evbox), + "button_press_event", G_CALLBACK(frame_delete_event), frame); + return evbox; +} + + /* ----- frame references -------------------------------------------------- */ @@ -576,7 +622,7 @@ static GtkWidget *build_frame_refs(const struct frame *frame) static void build_frames(GtkWidget *vbox) { struct frame *frame; - GtkWidget *tab, *label, *refs, *vars; + GtkWidget *tab, *label, *delete, *refs, *vars; int n = 0; destroy_all_children(GTK_CONTAINER(vbox)); @@ -593,9 +639,15 @@ static void build_frames(GtkWidget *vbox) label = build_frame_label(frame); gtk_table_attach_defaults(GTK_TABLE(tab), label, 0, 1, n*2, n*2+1); + + delete = build_frame_delete(frame); + gtk_table_attach_defaults(GTK_TABLE(tab), delete, + 0, 1, n*2+1, n*2+2); + refs = build_frame_refs(frame); gtk_table_attach_defaults(GTK_TABLE(tab), refs, 1, 2, n*2, n*2+1); + vars = build_vars(frame); gtk_table_attach_defaults(GTK_TABLE(tab), vars, 1, 2, n*2+1, n*2+2); diff --git a/gui_canvas.c b/gui_canvas.c index b73fd40..e19fcec 100644 --- a/gui_canvas.c +++ b/gui_canvas.c @@ -301,7 +301,8 @@ static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, case GDK_BackSpace: case GDK_Delete: case GDK_KP_Delete: - if (selected_inst && inst_delete(selected_inst)) { + if (selected_inst) { + inst_delete(selected_inst); tool_frame_update(); change_world(); } diff --git a/gui_status.c b/gui_status.c index c99825a..28c3985 100644 --- a/gui_status.c +++ b/gui_status.c @@ -444,8 +444,11 @@ static GtkWidget *add_label(GtkWidget *tab, int col, int row) GtkWidget *label; label = label_in_box_new(NULL); - gtk_table_attach_defaults(GTK_TABLE(tab), box_of_label(label), - col, col+1, row, row+1); + gtk_table_attach(GTK_TABLE(tab), box_of_label(label), + col, col+1, row, row+1, + GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 1); + /* 0 , 1 - padding */ + gtk_misc_set_alignment(GTK_MISC(label), 0, 0); gtk_label_set_selectable(GTK_LABEL(label), TRUE); return label; @@ -472,9 +475,9 @@ static GtkWidget *add_entry(GtkWidget *tab, int col, int row) void make_status_area(GtkWidget *vbox) { - GtkWidget *tab; + GtkWidget *tab, *sep; - tab = gtk_table_new(6, 3, FALSE); + tab = gtk_table_new(7, 3, FALSE); gtk_box_pack_start(GTK_BOX(vbox), tab, FALSE, TRUE, 0); /* types */ @@ -495,22 +498,27 @@ void make_status_area(GtkWidget *vbox) status_name = add_label(tab, 1, 2); status_entry = add_entry(tab, 2, 2); + /* separator */ + + sep = gtk_vseparator_new(); + gtk_table_attach_defaults(GTK_TABLE(tab), sep, 3, 4, 0, 3); + /* sys / user pos */ - status_sys_x = add_label(tab, 3, 0); - status_sys_y = add_label(tab, 3, 1); - status_user_x = add_label(tab, 4, 0); - status_user_y = add_label(tab, 4, 1); + status_sys_x = add_label(tab, 4, 0); + status_sys_y = add_label(tab, 4, 1); + status_user_x = add_label(tab, 5, 0); + status_user_y = add_label(tab, 5, 1); /* r / angle */ - status_r = add_label(tab, 3, 2); - status_angle = add_label(tab, 4, 2); + status_r = add_label(tab, 4, 2); + status_angle = add_label(tab, 5, 2); /* zoom / grid */ - status_zoom = add_label(tab, 5, 0); - status_grid = add_label(tab, 5, 1); + status_zoom = add_label(tab, 6, 0); + status_grid = add_label(tab, 6, 1); /* message bar */ diff --git a/inst.c b/inst.c index 007fcbb..b36ccb2 100644 --- a/inst.c +++ b/inst.c @@ -870,10 +870,12 @@ void inst_hover(struct inst *inst, struct draw_ctx *ctx, int on) } -int inst_delete(struct inst *inst) +void inst_delete(struct inst *inst) { - return inst->ops == &vec_ops ? - delete_vec(inst->vec) : delete_obj(inst->obj); + if (inst->ops == &vec_ops) + delete_vec(inst->vec); + else + delete_obj(inst->obj); } diff --git a/inst.h b/inst.h index 0c1a006..0267dc6 100644 --- a/inst.h +++ b/inst.h @@ -117,7 +117,7 @@ struct pix_buf *inst_draw_move(struct inst *inst, struct draw_ctx *ctx, struct coord pos, int i); int inst_do_move_to(struct inst *inst, struct vec *vec, int i); void inst_hover(struct inst *inst, struct draw_ctx *ctx, int on); -int inst_delete(struct inst *inst); +void inst_delete(struct inst *inst); void inst_debug(void); #endif /* !INST_H */