diff --git a/Makefile b/Makefile index fd61fca..54b1b27 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ gui_tools.o XPMS = point.xpm delete.xpm vec.xpm frame.xpm frame_locked.xpm frame_ready.xpm \ - line.xpm rect.xpm pad.xpm circ.xpm meas.xpm + line.xpm rect.xpm pad.xpm circ.xpm meas.xpm meas_x.xpm meas_y.xpm CFLAGS_GTK = `pkg-config --cflags gtk+-2.0` LIBS_GTK = `pkg-config --libs gtk+-2.0` diff --git a/README b/README index 244b3b2..61d2a1e 100644 --- a/README +++ b/README @@ -422,10 +422,10 @@ 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. If deleting a vector, all items -that reference it are deleted. +To delete an object, select the delete tool and click on the object. +Deleted objects can be undeleted by pressing "u". If any other changes +have been made since deletion, fped may misbehave. If deleting a vector, +all items that reference it are deleted as well. Experimental: new-style measurements diff --git a/gui.c b/gui.c index 3950ad6..99067ff 100644 --- a/gui.c +++ b/gui.c @@ -1225,7 +1225,7 @@ int gui_main(void) { root = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER); - gtk_window_set_default_size(GTK_WINDOW(root), 600, 400); + gtk_window_set_default_size(GTK_WINDOW(root), 620, 460); gtk_window_set_title(GTK_WINDOW(root), "fped"); /* get root->window */ diff --git a/gui_canvas.c b/gui_canvas.c index dc58f78..c83be41 100644 --- a/gui_canvas.c +++ b/gui_canvas.c @@ -26,6 +26,8 @@ #include "gui_canvas.h" +void (*highlight)(struct draw_ctx *ctx) = NULL; + static struct draw_ctx ctx; static struct coord curr_pos; static struct coord user_origin = { 0, 0 }; @@ -101,9 +103,12 @@ void redraw(void) aw = ctx.widget->allocation.width; ah = ctx.widget->allocation.height; - gdk_draw_rectangle(ctx.widget->window, gc_bg, TRUE, 0, 0, aw, ah); + gdk_draw_rectangle(ctx.widget->window, + instantiation_ok ? gc_bg : gc_bg_error, TRUE, 0, 0, aw, ah); inst_draw(&ctx); + if (highlight) + highlight(&ctx); tool_redraw(&ctx); } diff --git a/gui_canvas.h b/gui_canvas.h index 50837d2..84031e7 100644 --- a/gui_canvas.h +++ b/gui_canvas.h @@ -17,6 +17,14 @@ #include +/* + * "highlight" is invoked at the end of each redraw, for optional highlighting + * of objects. + */ + +extern void (*highlight)(struct draw_ctx *ctx); + + void redraw(void); GtkWidget *make_canvas(void); diff --git a/gui_inst.c b/gui_inst.c index c56ba8e..1fdf05f 100644 --- a/gui_inst.c +++ b/gui_inst.c @@ -159,6 +159,14 @@ void gui_hover_vec(struct inst *self, struct draw_ctx *ctx) } +void gui_highlight_vec(struct inst *self, struct draw_ctx *ctx) +{ + struct coord center = translate(ctx, self->u.rect.end); + + draw_circle(DA, gc_highlight, FALSE, center.x, center.y, VEC_EYE_R); +} + + void gui_draw_vec(struct inst *self, struct draw_ctx *ctx) { struct coord from = translate(ctx, self->base); diff --git a/gui_inst.h b/gui_inst.h index 276e7a9..ca67c43 100644 --- a/gui_inst.h +++ b/gui_inst.h @@ -50,6 +50,7 @@ void gui_draw_arc(struct inst *self, struct draw_ctx *ctx); void gui_draw_meas(struct inst *self, struct draw_ctx *ctx); void gui_draw_frame(struct inst *self, struct draw_ctx *ctx); +void gui_highlight_vec(struct inst *self, struct draw_ctx *ctx); void gui_hover_vec(struct inst *self, struct draw_ctx *ctx); void gui_hover_frame(struct inst *self, struct draw_ctx *ctx); diff --git a/gui_style.c b/gui_style.c index cf40a8c..076b4f0 100644 --- a/gui_style.c +++ b/gui_style.c @@ -1,5 +1,4 @@ -/* - * gui_style.c - GUI, style definitions +/* * gui_style.c - GUI, style definitions * * Written 2009 by Werner Almesberger * Copyright 2009 by Werner Almesberger @@ -22,8 +21,9 @@ #define INVALID "#00ffff" -GdkGC *gc_bg; +GdkGC *gc_bg, *gc_bg_error; GdkGC *gc_drag; +GdkGC *gc_highlight; GdkGC *gc_active_frame; GdkGC *gc_vec[mode_n]; GdkGC *gc_obj[mode_n]; @@ -61,6 +61,7 @@ static void style(GdkGC *gcs[mode_n], void gui_setup_style(GdkDrawable *drawable) { gc_bg = gc("#000000", 0); + gc_bg_error = gc("#000040", 0); gc_drag = gc("#ffffff", 2); /* inactive in+path active act+path selected */ style(gc_vec, "#202000", "#404020", "#909040", "#c0c080", "#ffff80"); @@ -69,7 +70,9 @@ void gui_setup_style(GdkDrawable *drawable) style(gc_ptext, "#404040", INVALID, "#ffffff", INVALID, "#ffffff"); style(gc_meas, "#280040", INVALID, "#ff00ff", INVALID, "#ffff80"); style(gc_frame, "#004000", "#205020", "#009000", INVALID, "#ffff80"); - gc_active_frame = gc("#00ff00", 2); + gc_active_frame = gc("#00ff00", 2); +// gc_highlight = gc("#ff8020", 2); + gc_highlight = gc("#ff90d0", 2); gc_frame[mode_hover] = gc_vec[mode_hover] = gc("#c00000", 1); } diff --git a/gui_style.h b/gui_style.h index 5b373a9..840e3d1 100644 --- a/gui_style.h +++ b/gui_style.h @@ -88,8 +88,9 @@ /* ----- canvas drawing styles --------------------------------------------- */ -extern GdkGC *gc_bg; +extern GdkGC *gc_bg, *gc_bg_error; extern GdkGC *gc_drag; +extern GdkGC *gc_highlight; extern GdkGC *gc_active_frame; extern GdkGC *gc_vec[mode_n]; extern GdkGC *gc_obj[mode_n]; diff --git a/gui_tools.c b/gui_tools.c index 19edd09..15f1ea5 100644 --- a/gui_tools.c +++ b/gui_tools.c @@ -22,6 +22,7 @@ #include "gui_util.h" #include "gui_style.h" #include "gui_inst.h" +#include "gui_canvas.h" #include "gui_status.h" #include "gui.h" #include "gui_tools.h" @@ -33,6 +34,8 @@ #include "icons/frame_ready.xpm" #include "icons/line.xpm" #include "icons/meas.xpm" +#include "icons/meas_x.xpm" +#include "icons/meas_y.xpm" #include "icons/pad.xpm" #include "icons/point.xpm" #include "icons/delete.xpm" @@ -45,6 +48,7 @@ struct tool_ops { void (*tool_selected)(void); + void (*tool_deselected)(void); void (*click)(struct draw_ctx *ctx, struct coord pos); struct pix_buf *(*drag_new)(struct draw_ctx *ctx, struct inst *from, struct coord to); @@ -517,11 +521,63 @@ static int end_new_meas(struct draw_ctx *ctx, } +static int meas_x_pick_vec(struct inst *inst, void *ctx) +{ + struct vec *vec = inst->vec; + struct coord min; + + if (!vec->samples) + return 0; + min = meas_find_min(lt_xy, vec->samples); + return inst->u.rect.end.x == min.x && inst->u.rect.end.y == min.y; +} + + +static void highlight_vecs(struct draw_ctx *ctx) +{ + inst_highlight_vecs(ctx, meas_x_pick_vec, NULL); +} + + +static void tool_selected_meas_x(void) +{ + highlight = highlight_vecs; + redraw(); +} + + +static void tool_selected_meas_y(void) +{ + highlight = NULL; + redraw(); +} + + +static void tool_deselected_meas(void) +{ + highlight = NULL; + redraw(); +} + + static struct tool_ops meas_ops = { .drag_new = drag_new_line, .end_new = end_new_meas, }; +static struct tool_ops meas_ops_x = { + .tool_selected = tool_selected_meas_x, + .tool_deselected= tool_deselected_meas, + .drag_new = drag_new_line, + .end_new = end_new_meas, +}; +static struct tool_ops meas_ops_y = { + .tool_selected = tool_selected_meas_y, + .tool_deselected= tool_deselected_meas, + .drag_new = drag_new_line, + .end_new = end_new_meas, +}; + /* ----- frame helper ------------------------------------------------------ */ @@ -828,6 +884,8 @@ static void tool_select(GtkWidget *evbox, struct tool_ops *ops) GdkColor col; if (active_tool) { + if (active_ops && active_ops->tool_deselected) + active_ops->tool_deselected(); col = get_color(TOOL_UNSELECTED); gtk_widget_modify_bg(active_tool, GTK_STATE_NORMAL, &col); active_tool = NULL; @@ -940,7 +998,10 @@ GtkWidget *gui_setup_tools(GdkDrawable *drawable) last = tool_button(bar, drawable, xpm_line, last, &line_ops); last = tool_button(bar, drawable, xpm_rect, last, &rect_ops); last = tool_button(bar, drawable, xpm_circ, last, &circ_ops); + tool_separator(bar); last = tool_button(bar, drawable, xpm_meas, last, &meas_ops); + last = tool_button(bar, drawable, xpm_meas_x, last, &meas_ops_x); + last = tool_button(bar, drawable, xpm_meas_y, last, &meas_ops_y); frame_image = gtk_widget_ref(make_image(drawable, xpm_frame)); frame_image_locked = diff --git a/icons/meas.fig b/icons/meas.fig index 343da73..edc649a 100644 --- a/icons/meas.fig +++ b/icons/meas.fig @@ -10,10 +10,10 @@ Single 2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 3900 3300 3900 3900 -2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 - 5700 3300 5700 3900 + 3900 3600 4200 4200 2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 1 1 2 0 0 10.00 450.00 450.00 0 0 10.00 450.00 450.00 - 3900 3600 5700 3600 + 4050 3900 5550 3150 +2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 5400 2850 5700 3450 diff --git a/icons/meas_x.fig b/icons/meas_x.fig new file mode 100644 index 0000000..2213c28 --- /dev/null +++ b/icons/meas_x.fig @@ -0,0 +1,23 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +6 3975 2775 5625 4125 +2 1 0 10 0 7 45 -1 -1 0.000 0 1 -1 0 0 2 + 4050 3600 5550 2850 +2 1 0 10 21 7 50 -1 -1 0.000 0 1 -1 0 0 2 + 5550 2850 5550 3900 +2 1 0 10 21 7 50 -1 -1 0.000 0 1 -1 0 0 2 + 4050 3600 4050 3900 +2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 1 1 2 + 0 0 10.00 450.00 450.00 + 0 0 10.00 450.00 450.00 + 4050 3900 5550 3900 +-6 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 diff --git a/icons/meas_y.fig b/icons/meas_y.fig new file mode 100644 index 0000000..3bf698e --- /dev/null +++ b/icons/meas_y.fig @@ -0,0 +1,23 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +6 3825 2700 5475 4200 +2 1 0 10 21 7 50 -1 -1 0.000 0 0 -1 1 1 2 + 0 0 10.00 450.00 450.00 + 0 0 10.00 450.00 450.00 + 5250 2775 5250 4125 +2 1 0 10 21 7 50 -1 -1 0.000 0 1 -1 0 0 2 + 3900 4125 5250 4125 +2 1 0 10 0 7 45 -1 -1 0.000 0 1 -1 0 0 2 + 3900 4125 4650 2775 +2 1 0 10 21 7 50 -1 -1 0.000 0 1 -1 0 0 2 + 4650 2775 5250 2775 +-6 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 diff --git a/inst.c b/inst.c index 4ded114..82b4ba0 100644 --- a/inst.c +++ b/inst.c @@ -841,6 +841,17 @@ void inst_draw(struct draw_ctx *ctx) } +void inst_highlight_vecs(struct draw_ctx *ctx, + int (*pick)(struct inst *inst, void *user), void *user) +{ + struct inst *inst; + + for (inst = insts[ip_vec]; inst; inst = inst->next) + if (pick(inst, user)) + gui_highlight_vec(inst, ctx); +} + + struct pix_buf *inst_draw_move(struct inst *inst, struct draw_ctx *ctx, struct coord pos, int i) { diff --git a/inst.h b/inst.h index a5b4e64..00f9dce 100644 --- a/inst.h +++ b/inst.h @@ -114,6 +114,8 @@ void inst_commit(void); void inst_revert(void); void inst_draw(struct draw_ctx *ctx); +void inst_highlight_vecs(struct draw_ctx *ctx, + int (*pick)(struct inst *inst, void *user), void *user); 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); diff --git a/meas.c b/meas.c index f676c8d..c8e5061 100644 --- a/meas.c +++ b/meas.c @@ -75,25 +75,25 @@ void meas_post(struct vec *vec, struct coord pos) } -static int lt_x(struct coord a, struct coord b) +int lt_x(struct coord a, struct coord b) { return a.x < b.x; } -static int lt_y(struct coord a, struct coord b) +int lt_y(struct coord a, struct coord b) { return a.y < b.y; } -static int lt_xy(struct coord a, struct coord b) +int lt_xy(struct coord a, struct coord b) { return a.y < b.y || (a.y == b.y && a.x < b.x); } -static int (*lt_op[mt_n])(struct coord a, struct coord b) = { +static lt_op_type lt_op[mt_n] = { lt_xy, lt_x, lt_y, @@ -109,7 +109,7 @@ static int is_next[mt_n] = { }; -static int better_next(int (*lt)(struct coord a, struct coord b), +static int better_next(lt_op_type lt, struct coord a0, struct coord b0, struct coord b) { /* if we don't have any suitable point A0 < B0 yet, use this one */ @@ -143,12 +143,64 @@ static int better_next(int (*lt)(struct coord a, struct coord b), } +/* + * In order to obtain a stable order, we sort points equal on the measured + * coordinate also by xy: + * + * if (*a < a0) use *a + * else if (*a == a0 && *a pos; + while (s) { + if (lt(s->pos, min) || + (!lt(min, s->pos) && lt_xy(s->pos, min))) + min = s->pos; + s = s->next; + } + return min; +} + + +struct coord meas_find_next(lt_op_type lt, const struct sample *s, + struct coord ref) +{ + struct coord next; + + next = s->pos; + while (s) { + if (better_next(lt, ref, next, s->pos)) + next = s->pos; + s = s->next; + } + return next; +} + + +struct coord meas_find_max(lt_op_type lt, const struct sample *s) +{ + struct coord max; + + max = s->pos; + while (s) { + if (lt(max, s->pos) || + (!lt(s->pos, max) && lt_xy(max, s->pos))) + max = s->pos; + s = s->next; + } + return max; +} + + int instantiate_meas(void) { struct meas *meas; struct coord a0, b0; - const struct sample *a, *b; - int (*lt)(struct coord a, struct coord b); + lt_op_type lt; struct num offset; for (meas = measurements; meas; meas = meas->next) { @@ -156,31 +208,11 @@ int instantiate_meas(void) continue; lt = lt_op[meas->type]; - - /* - * In order to obtain a stable order, we sort points equal on - * the measured coordinate also by xy: - * - * if (*a < a0) use *a - * else if (*a == a0 && *a low->samples->pos; - for (a = meas->low->samples; a; a = a->next) - if (lt(a->pos, a0) || - (!lt(a0, a->pos) && lt_xy(a->pos, a0))) - a0 = a->pos; - - b0 = meas->high->samples->pos; - for (b = meas->high->samples; b; b = b->next) { - if (is_next[meas->type]) { - if (better_next(lt, a0, b0, b->pos)) - b0 = b->pos; - } else { - if (lt(b0, b->pos) || - (!lt(b->pos, b0) && lt_xy(b0, b->pos))) - b0 = b->pos; - } - } + a0 = meas_find_min(lt, meas->low->samples); + if (is_next[meas->type]) + b0 = meas_find_next(lt, meas->high->samples, a0); + else + b0 = meas_find_max(lt, meas->high->samples); offset = eval_unit(meas->offset, root_frame); if (is_undef(offset)) diff --git a/meas.h b/meas.h index 5919a0a..51d5abd 100644 --- a/meas.h +++ b/meas.h @@ -17,6 +17,9 @@ #include "obj.h" +typedef int (*lt_op_type)(struct coord a, struct coord b); + + struct meas { enum meas_type { mt_xy_next, @@ -35,10 +38,21 @@ struct meas { struct meas *next; }; +struct sample; + extern struct meas *measurements; +int lt_x(struct coord a, struct coord b); +int lt_y(struct coord a, struct coord b); +int lt_xy(struct coord a, struct coord b); + +struct coord meas_find_min(lt_op_type lt, const struct sample *s); +struct coord meas_find_next(lt_op_type lt, const struct sample *s, + struct coord ref); +struct coord meas_find_max(lt_op_type lt, const struct sample *s); + void meas_start(void); void meas_post(struct vec *vec, struct coord pos); int instantiate_meas(void); diff --git a/obj.c b/obj.c index 7cef142..5cd03ad 100644 --- a/obj.c +++ b/obj.c @@ -32,6 +32,7 @@ char *part_name = NULL; struct frame *frames = NULL; struct frame *root_frame = NULL; struct frame *active_frame = NULL; +int instantiation_ok; static int generate_frame(struct frame *frame, struct coord base, @@ -273,5 +274,6 @@ int instantiate(void) inst_commit(); else inst_revert(); + instantiation_ok = ok; return ok; } diff --git a/obj.h b/obj.h index e0704a3..ed9d639 100644 --- a/obj.h +++ b/obj.h @@ -181,6 +181,7 @@ extern char *part_name; extern struct frame *frames; extern struct frame *root_frame; extern struct frame *active_frame; +extern int instantiation_ok; int instantiate(void);