From 8377ab0e0d575fc7dfd15eff11f969b3e33a0ab0 Mon Sep 17 00:00:00 2001 From: werner Date: Tue, 4 Aug 2009 18:03:06 +0000 Subject: [PATCH] - previous Makefile change was: tentative fix for compatibility with older ImageMagick versions (reported by Alvaro Lopes) - we can now also select the frame's origin as a reference - added general frame selection logic - make sure we always use %s when passing names to status_set_name - we can now drag endpoints (in progress) git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5385 99fdad57-331a-0410-800a-d7fa5415bdb3 --- gui.c | 4 +- gui_inst.c | 39 ++++++++++++- gui_inst.h | 2 + gui_style.c | 4 +- gui_style.h | 1 + gui_tools.c | 158 ++++++++++++++++++++++++++++++++++++++++++---------- inst.c | 107 ++++++++++++++++++++++++++++++++--- inst.h | 6 +- obj.c | 4 +- 9 files changed, 281 insertions(+), 44 deletions(-) diff --git a/gui.c b/gui.c index 07011f4..b5dbbab 100644 --- a/gui.c +++ b/gui.c @@ -115,7 +115,7 @@ static void edit_var(struct var *var) inst_select_outside(var, unselect_var); label_in_box_bg(var->widget, COLOR_VAR_EDITING); status_set_type_entry("name ="); - status_set_name(var->name); + status_set_name("%s", var->name); edit_unique(&var->name, validate_var_name, var); } @@ -493,7 +493,7 @@ static void edit_frame(struct frame *frame) inst_select_outside(frame, unselect_frame); label_in_box_bg(frame->label, COLOR_FRAME_EDITING); status_set_type_entry("name ="); - status_set_name(frame->name); + status_set_name("%s", frame->name); edit_unique(&frame->name, validate_frame_name, frame); } diff --git a/gui_inst.c b/gui_inst.c index 7b00517..67843e6 100644 --- a/gui_inst.c +++ b/gui_inst.c @@ -393,7 +393,8 @@ void gui_draw_meas(struct inst *self, struct draw_ctx *ctx) /* ----- frame ------------------------------------------------------------- */ -unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale) +unit_type gui_dist_frame_eye(struct inst *self, struct coord pos, + unit_type scale) { unit_type d; @@ -402,6 +403,40 @@ unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale) } +static unit_type dist_from_corner_line(struct inst *self, struct coord pos, + struct coord vec, unit_type scale) +{ + struct coord ref; + + ref.x = self->bbox.min.x; + ref.y = self->bbox.max.y; + return dist_line(pos, ref, add_vec(ref, vec))/scale; +} + + +unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale) +{ + unit_type d_min, d; + struct coord vec; + + d_min = dist_point(pos, self->base)/scale; + + vec.x = FRAME_SHORT_X*scale; + vec.y = 0; + d = dist_from_corner_line(self, pos, vec, scale); + if (d < d_min) + d_min = d; + + vec.x = 0; + vec.y = FRAME_SHORT_Y*scale; + d = dist_from_corner_line(self, pos, vec, scale); + if (d < d_min) + d_min = d; + + return d_min > SELECT_R ? -1 : d_min; +} + + void gui_hover_frame(struct inst *self, struct draw_ctx *ctx) { struct coord center = translate(ctx, self->base); @@ -418,7 +453,7 @@ void gui_draw_frame(struct inst *self, struct draw_ctx *ctx) struct coord corner = { self->bbox.min.x, self->bbox.max.y }; GdkGC *gc; - gc = gc_frame[get_mode(self)]; + gc = self->u.frame.active ? gc_active_frame : gc_frame[get_mode(self)]; draw_eye(ctx, gc, center, FRAME_EYE_R1, FRAME_EYE_R2); if (!self->u.frame.ref->name) return; diff --git a/gui_inst.h b/gui_inst.h index 0590dc4..276e7a9 100644 --- a/gui_inst.h +++ b/gui_inst.h @@ -39,6 +39,8 @@ unit_type gui_dist_pad(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_arc(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_meas(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale); +unit_type gui_dist_frame_eye(struct inst *self, struct coord pos, + unit_type scale); void gui_draw_vec(struct inst *self, struct draw_ctx *ctx); void gui_draw_line(struct inst *self, struct draw_ctx *ctx); diff --git a/gui_style.c b/gui_style.c index 9e9bedc..cf40a8c 100644 --- a/gui_style.c +++ b/gui_style.c @@ -24,6 +24,7 @@ GdkGC *gc_bg; GdkGC *gc_drag; +GdkGC *gc_active_frame; GdkGC *gc_vec[mode_n]; GdkGC *gc_obj[mode_n]; GdkGC *gc_pad[mode_n]; @@ -67,7 +68,8 @@ void gui_setup_style(GdkDrawable *drawable) style(gc_pad, "#400000", INVALID, "#ff0000", INVALID, "#ffff80"); style(gc_ptext, "#404040", INVALID, "#ffffff", INVALID, "#ffffff"); style(gc_meas, "#280040", INVALID, "#ff00ff", INVALID, "#ffff80"); - style(gc_frame, "#004000", "#205020", "#00ff00", INVALID, INVALID); + style(gc_frame, "#004000", "#205020", "#009000", INVALID, "#ffff80"); + gc_active_frame = gc("#00ff00", 2); gc_frame[mode_hover] = gc_vec[mode_hover] = gc("#c00000", 1); } diff --git a/gui_style.h b/gui_style.h index 8cd73e0..54f4f0f 100644 --- a/gui_style.h +++ b/gui_style.h @@ -84,6 +84,7 @@ extern GdkGC *gc_bg; extern GdkGC *gc_drag; +extern GdkGC *gc_active_frame; extern GdkGC *gc_vec[mode_n]; extern GdkGC *gc_obj[mode_n]; extern GdkGC *gc_pad[mode_n]; diff --git a/gui_tools.c b/gui_tools.c index e5e76bc..77d1b94 100644 --- a/gui_tools.c +++ b/gui_tools.c @@ -11,6 +11,8 @@ */ +#include +#include #include #include "util.h" @@ -36,9 +38,10 @@ struct tool_ops { - struct pix_buf *(*drag)(struct draw_ctx *ctx, struct inst *from, + struct pix_buf *(*drag_new)(struct draw_ctx *ctx, struct inst *from, struct coord to); - int (*end)(struct draw_ctx *ctx, struct inst *from, struct inst *to); + int (*end_new)(struct draw_ctx *ctx, struct inst *from, + struct inst *to); }; @@ -47,7 +50,16 @@ static GtkWidget *active_tool; static struct tool_ops *active_ops = NULL; static struct inst *hover_inst = NULL; -static struct inst *drag; +static struct drag_state { + struct inst *new; /* non-NULL if dragging a new object */ + int anchors_n; /* number of anchors, 0 if no moving */ + int anchor_i; /* current anchor */ + struct vec **anchors[3]; +} drag = { + .new = NULL, + .anchors_n = 0, +}; + static struct pix_buf *pix_buf; static struct tool_ops vec_ops; @@ -104,8 +116,8 @@ static int end_new_line(struct draw_ctx *ctx, static struct tool_ops line_ops = { - .drag = drag_new_line, - .end = end_new_line, + .drag_new = drag_new_line, + .end_new = end_new_line, }; @@ -156,8 +168,8 @@ static int end_new_rect(struct draw_ctx *ctx, static struct tool_ops rect_ops = { - .drag = drag_new_rect, - .end = end_new_rect, + .drag_new = drag_new_rect, + .end_new = end_new_rect, }; @@ -196,12 +208,77 @@ static int end_new_circ(struct draw_ctx *ctx, static struct tool_ops circ_ops = { - .drag = drag_new_circ, - .end = end_new_circ, + .drag_new = drag_new_circ, + .end_new = end_new_circ, }; -/* ----- mouse actions ----------------------------------------------------- */ +/* ----- moving references ------------------------------------------------- */ + + +static int may_move(struct inst *curr) +{ + if (!selected_inst) + return 0; + if (drag.anchors_n) + return 0; /* already moving something else */ + drag.anchors_n = inst_anchors(selected_inst, drag.anchors); + for (drag.anchor_i = 0; drag.anchor_i != drag.anchors_n; + drag.anchor_i++) + if (*drag.anchors[drag.anchor_i] == inst_get_vec(curr)) + return 1; + drag.anchors_n = 0; + return 0; +} + + +static int would_be_equal(const struct drag_state *state, + int a, int b, struct inst *curr) +{ + const struct vec *va; + const struct vec *vb; + + va = a == state->anchor_i ? inst_get_vec(curr) : *state->anchors[a]; + vb = b == state->anchor_i ? inst_get_vec(curr) : *state->anchors[b]; + return va == vb; +} + + +static int may_move_to(const struct drag_state *state, struct inst *curr) +{ + assert(selected_inst); + assert(state->anchors_n); + switch (state->anchors_n) { + case 3: + if (would_be_equal(state, 0, 2, curr)) + return 0; + /* fall through */ + case 2: + if (would_be_equal(state, 0, 1, curr)) + return 0; + /* fall through */ + case 1: + return 1; + default: + abort(); + } +} + + +static void do_move_to(struct drag_state *state, struct inst *curr) +{ + struct vec *old; + + assert(may_move_to(state, curr)); + old = *state->anchors[state->anchor_i]; + if (old) + old->n_refs--; + *state->anchors[state->anchor_i] = inst_get_ref(curr); + state->anchors_n = 0; +} + + +/* ----- hover ------------------------------------------------------------- */ void tool_dehover(struct draw_ctx *ctx) @@ -214,29 +291,46 @@ void tool_dehover(struct draw_ctx *ctx) void tool_hover(struct draw_ctx *ctx, struct coord pos) { - struct inst *inst; + struct inst *curr; - if (!active_ops) - return; - inst = inst_find_point(ctx, pos); - if (inst != hover_inst) + curr = inst_find_point(ctx, pos); + if (curr && !active_ops) { + if (drag.anchors_n) { + if (!may_move_to(&drag, curr)) + curr = NULL; + } else { + if (!may_move(curr)) + curr = NULL; + drag.anchors_n = 0; + } + } + if (curr != hover_inst) tool_dehover(ctx); - if (inst) { - inst_hover(inst, ctx, 1); - hover_inst = inst; + if (curr) { + inst_hover(curr, ctx, 1); + hover_inst = curr; } } +/* ----- mouse actions ----------------------------------------------------- */ + + int tool_consider_drag(struct draw_ctx *ctx, struct coord pos) { - if (!active_ops) - return 0; - drag = inst_find_point(ctx, pos); - if (!drag) + struct inst *curr; + + assert(!drag.new); + assert(!drag.anchors_n); + curr = inst_find_point(ctx, pos); + if (!curr) return 0; pix_buf = NULL; - return 1; + if (active_ops) { + drag.new = curr; + return 1; + } + return may_move(curr); } @@ -245,7 +339,7 @@ void tool_drag(struct draw_ctx *ctx, struct coord to) if (pix_buf) restore_pix_buf(pix_buf); tool_hover(ctx, to); - pix_buf = active_ops->drag(ctx, drag, to); + pix_buf = drag.new ? active_ops->drag_new(ctx, drag.new, to) : NULL; } @@ -255,22 +349,28 @@ void tool_cancel_drag(struct draw_ctx *ctx) tool_reset(); if (pix_buf) restore_pix_buf(pix_buf); - drag = NULL; + drag.new = NULL; active_ops = NULL; + drag.anchors_n = 0; } int tool_end_drag(struct draw_ctx *ctx, struct coord to) { - struct inst *from = drag; + struct drag_state state = drag; struct inst *end; struct tool_ops *ops = active_ops; tool_cancel_drag(ctx); end = inst_find_point(ctx, to); - if (end) - return ops->end(ctx, from, end); - return 0; + if (!end) + return 0; + if (state.new) + return ops->end_new(ctx, state.new, end); + if (!may_move_to(&state, end)) + return 0; + do_move_to(&state, end); + return 1; } diff --git a/inst.c b/inst.c index 3ece47f..742aa5c 100644 --- a/inst.c +++ b/inst.c @@ -33,6 +33,7 @@ struct inst_ops { unit_type (*distance)(struct inst *self, struct coord pos, unit_type scale); void (*select)(struct inst *self); + int (*anchors)(struct inst *self, struct vec ***anchors); }; enum inst_prio { @@ -179,9 +180,9 @@ struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos) found = NULL; for (inst = insts[ip_frame]; inst; inst = inst->next) { - if (!inst->active || !inst->ops->distance) + if (!inst->active) continue; - dist = inst->ops->distance(inst, pos, ctx->scale); + dist = gui_dist_frame_eye(inst, pos, ctx->scale); if (dist >= 0 && (!found || best_dist > dist)) { found = inst; best_dist = dist; @@ -225,6 +226,22 @@ struct vec *inst_get_ref(const struct inst *inst) } +struct vec *inst_get_vec(const struct inst *inst) +{ + if (inst->ops == &vec_ops) + return inst->vec; + if (inst->ops == &frame_ops) + return NULL; + abort(); +} + + +int inst_anchors(struct inst *inst, struct vec ***anchors) +{ + return inst->ops->anchors ? inst->ops->anchors(inst, anchors) : 0; +} + + void inst_deselect(void) { if (selected_inst) @@ -343,7 +360,7 @@ static int validate_vec_name(const char *s, void *ctx) static void vec_op_select(struct inst *self) { status_set_type_entry("ref ="); - status_set_name(self->vec->name ? self->vec->name : ""); + status_set_name("%s", self->vec->name ? self->vec->name : ""); rect_status(self->base, self->u.rect.end, -1); edit_unique_null(&self->vec->name, validate_vec_name, self->vec); edit_x(&self->vec->x); @@ -351,12 +368,20 @@ static void vec_op_select(struct inst *self) } +static int vec_op_anchors(struct inst *inst, struct vec ***anchors) +{ + anchors[0] = &inst->vec->base; + return 1; +} + + static struct inst_ops vec_ops = { .debug = vec_op_debug, .draw = gui_draw_vec, .hover = gui_hover_vec, .distance = gui_dist_vec, .select = vec_op_select, + .anchors = vec_op_anchors, }; @@ -391,11 +416,22 @@ static void line_op_select(struct inst *self) } +static int line_op_anchors(struct inst *inst, struct vec ***anchors) +{ + struct obj *obj = inst->obj; + + anchors[0] = &obj->base; + anchors[1] = &obj->u.rect.other; + return 2; +} + + static struct inst_ops line_ops = { .debug = line_op_debug, .draw = gui_draw_line, .distance = gui_dist_line, .select = line_op_select, + .anchors = line_op_anchors, }; @@ -437,6 +473,7 @@ static struct inst_ops rect_ops = { .draw = gui_draw_rect, .distance = gui_dist_rect, .select = rect_op_select, + .anchors = line_op_anchors, }; @@ -481,17 +518,28 @@ static int validate_pad_name(const char *s, void *ctx) static void pad_op_select(struct inst *self) { status_set_type_entry("label ="); - status_set_name(self->u.name); + status_set_name("%s", self->u.name); rect_status(self->bbox.min, self->bbox.max, -1); edit_name(&self->obj->u.pad.name, validate_pad_name, NULL); } +static int pad_op_anchors(struct inst *inst, struct vec ***anchors) +{ + struct obj *obj = inst->obj; + + anchors[0] = &obj->base; + anchors[1] = &obj->u.pad.other; + return 2; +} + + static struct inst_ops pad_ops = { .debug = pad_op_debug, .draw = gui_draw_pad, .distance = gui_dist_pad, .select = pad_op_select, + .anchors = pad_op_anchors, }; @@ -532,11 +580,23 @@ static void arc_op_select(struct inst *self) } +static int arc_op_anchors(struct inst *inst, struct vec ***anchors) +{ + struct obj *obj = inst->obj; + + anchors[0] = &obj->base; + anchors[1] = &obj->u.arc.start; + anchors[2] = &obj->u.arc.end; + return 3; +} + + static struct inst_ops arc_ops = { .debug = arc_op_debug, .draw = gui_draw_arc, .distance = gui_dist_arc, .select = arc_op_select, + .anchors = arc_op_anchors, }; @@ -590,11 +650,22 @@ static void meas_op_select(struct inst *self) } +static int meas_op_anchors(struct inst *inst, struct vec ***anchors) +{ + struct obj *obj = inst->obj; + + anchors[0] = &obj->base; + anchors[1] = &obj->u.meas.other; + return 2; +} + + static struct inst_ops meas_ops = { .debug = meas_op_debug, .draw = gui_draw_meas, .distance = gui_dist_meas, .select = meas_op_select, + .anchors = meas_op_anchors, }; @@ -640,19 +711,39 @@ static void frame_op_debug(struct inst *self) } +static void frame_op_select(struct inst *self) +{ + rect_status(self->bbox.min, self->bbox.max, -1); + status_set_type_entry("name ="); + status_set_name("%s", self->u.frame.ref->name); +} + + +static int frame_op_anchors(struct inst *inst, struct vec ***anchors) +{ + anchors[0] = &inst->vec->base; + return 1; +} + + static struct inst_ops frame_ops = { - .debug = frame_op_debug, - .draw = gui_draw_frame, - .hover = gui_hover_frame, + .debug = frame_op_debug, + .draw = gui_draw_frame, + .hover = gui_hover_frame, + .distance = gui_dist_frame, + .select = frame_op_select, + .anchors = frame_op_anchors, }; -void inst_begin_frame(const struct frame *frame, struct coord base, int active) +void inst_begin_frame(const struct frame *frame, struct coord base, + int active, int is_active_frame) { struct inst *inst; inst = add_inst(&frame_ops, ip_frame, base); inst->u.frame.ref = frame; + inst->u.frame.active = is_active_frame; inst->active = active; curr_frame = inst; } diff --git a/inst.h b/inst.h index c8cdda8..5a834c4 100644 --- a/inst.h +++ b/inst.h @@ -51,6 +51,7 @@ struct inst { union { struct { const struct frame *ref; + int active; } frame; const char *name; struct { @@ -81,7 +82,9 @@ void inst_deselect(void); struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos); struct coord inst_get_point(const struct inst *inst); +int inst_anchors(struct inst *inst, struct vec ***anchors); struct vec *inst_get_ref(const struct inst *inst); +struct vec *inst_get_vec(const struct inst *inst); int inst_vec(struct vec *vec, struct coord base); int inst_line(struct obj *obj, struct coord a, struct coord b, unit_type width); @@ -95,7 +98,8 @@ int inst_meas(struct obj *obj, struct coord from, struct coord to, void inst_begin_active(int active); void inst_end_active(void); -void inst_begin_frame(const struct frame *frame, struct coord base, int active); +void inst_begin_frame(const struct frame *frame, struct coord base, + int active, int is_active_frame); void inst_end_frame(const struct frame *frame); struct bbox inst_get_bbox(void); diff --git a/obj.c b/obj.c index d3f5970..a4ce533 100644 --- a/obj.c +++ b/obj.c @@ -244,7 +244,9 @@ static int generate_frame(struct frame *frame, struct coord base, /* * We ensure during construction that frames can never recurse. */ - inst_begin_frame(frame, base, active && frame == active_frame); + inst_begin_frame(frame, base, + active && parent == active_frame, + active && frame == active_frame); frame->curr_parent = parent; ok = iterate_tables(frame, frame->tables, base, active); inst_end_frame(frame);