1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-06-24 16:11:40 +03:00

Added delete/undelete.

- when moving a point, we no longer restrict the area around the original
  position once the drag radius has been left
- objects can now be deleted by selecting them and pressing Delete
- deleted objects can be restored by pressing "u"



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5387 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2009-08-05 00:32:38 +00:00
parent 5d7ab083a3
commit 3db91b5c1b
11 changed files with 365 additions and 13 deletions

View File

@ -10,7 +10,7 @@
# (at your option) any later version.
#
OBJS = fped.o expr.o coord.o obj.o inst.o util.o error.o \
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
unparse.o \
cpp.o lex.yy.o y.tab.o \
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \

4
README
View File

@ -348,9 +348,11 @@ GUI
Keys:
space reset user coordinates
Space reset user coordinates
+, = zoom in (like mouse wheel forward)
- zoom out (like mouse wheel backward)
. cursor position to screen center (like middle click)
* zoom and center to extents
# zoom and center to currently active frame instance
Delete delete the currently selected object
U undelete the previously deleted object

2
TODO
View File

@ -19,6 +19,7 @@ Style:
Bugs:
- default silk width has no business being hard-coded in obj.c
- after moving, arc sometimes wrap the wrong way
- undelete only works if not much has changed since the deletion
Code cleanup:
- merge edit_unique with edit_name
@ -26,7 +27,6 @@ Code cleanup:
- add regression tests
Open decisions:
- decide on table presentation (merge frame and vars into single entity ?)
- Q: should loop be (start, last) or (start, iterations) ? or start ... last ?
- change vector circle color ? (also, highlight on hover ?)
- Q: allow reassignment of vector names ?

286
delete.c Normal file
View File

@ -0,0 +1,286 @@
/*
* delete.c - Object deletion
*
* Written 2009 by Werner Almesberger
* Copyright 2009 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <stdlib.h>
#include <assert.h>
#include "util.h"
#include "error.h"
#include "expr.h"
#include "obj.h"
#include "delete.h"
static struct deletion {
enum del_type {
dt_vec,
dt_obj,
} type;
union {
struct {
struct vec *ref;
struct vec *prev;
} vec;
struct {
struct obj *ref;
struct obj *prev;
} obj;
} u;
struct deletion *next;
} *deletions = NULL;
static struct deletion *new_deletion(enum del_type type)
{
struct deletion *del;
del = alloc_type(struct deletion);
del->type = type;
del->next = deletions;
deletions = del;
return del;
}
/* ----- vectors ----------------------------------------------------------- */
static void dereference_vec(struct vec *vec)
{
assert(!vec->n_refs);
put_vec(vec->base);
}
static void destroy_vec(struct vec *vec)
{
assert(!vec->n_refs);
free_expr(vec->x);
free_expr(vec->y);
free(vec);
}
static void rereference_vec(struct vec *vec)
{
get_vec(vec->base);
}
int delete_vec(struct vec *vec)
{
struct vec *walk, *prev;
struct deletion *del;
if (vec->n_refs) {
fail("vector has %d reference%s", vec->n_refs,
vec->n_refs == 1 ? "" : "s");
return 0;
}
prev = NULL;
for (walk = vec->frame->vecs; walk != vec; walk = walk->next)
prev = walk;
if (prev)
prev->next = vec->next;
else
vec->frame->vecs = vec->next;
dereference_vec(vec);
del = new_deletion(dt_vec);
del->u.vec.ref = vec;
del->u.vec.prev = prev;
return 1;
}
static void undelete_vec(struct vec *vec, struct vec *prev)
{
if (prev) {
assert(vec->next == prev->next);
prev->next = vec;
} else {
assert(vec->next == vec->frame->vecs);
vec->frame->vecs = vec;
}
rereference_vec(vec);
}
/* ----- objects ----------------------------------------------------------- */
static void dereference_obj(struct obj *obj)
{
switch (obj->type) {
case ot_frame:
/* nothing */
break;
case ot_pad:
put_vec(obj->u.pad.other);
break;
case ot_line:
put_vec(obj->u.line.other);
break;
case ot_rect:
put_vec(obj->u.rect.other);
break;
case ot_arc:
put_vec(obj->u.arc.start);
put_vec(obj->u.arc.end);
break;
case ot_meas:
put_vec(obj->u.meas.other);
break;
default:
abort();
}
put_vec(obj->base);
}
static void destroy_obj(struct obj *obj)
{
switch (obj->type) {
case ot_frame:
/* nothing */
break;
case ot_pad:
free(obj->u.pad.name);
break;
case ot_line:
free_expr(obj->u.line.width);
break;
case ot_rect:
free_expr(obj->u.rect.width);
break;
case ot_arc:
free_expr(obj->u.arc.width);
break;
case ot_meas:
free_expr(obj->u.meas.offset);
break;
default:
abort();
}
free(obj);
}
static void rereference_obj(struct obj *obj)
{
switch (obj->type) {
case ot_frame:
/* nothing */
break;
case ot_pad:
get_vec(obj->u.pad.other);
break;
case ot_line:
get_vec(obj->u.line.other);
break;
case ot_rect:
get_vec(obj->u.rect.other);
break;
case ot_arc:
get_vec(obj->u.arc.start);
get_vec(obj->u.arc.end);
break;
case ot_meas:
get_vec(obj->u.meas.other);
break;
default:
abort();
}
get_vec(obj->base);
}
int delete_obj(struct obj *obj)
{
struct obj *walk, *prev;
struct deletion *del;
prev = NULL;
for (walk = obj->frame->objs; walk != obj; walk = walk->next)
prev = walk;
if (prev)
prev->next = obj->next;
else
obj->frame->objs = obj->next;
dereference_obj(obj);
del = new_deletion(dt_obj);
del->u.obj.ref = obj;
del->u.obj.prev = prev;
return 1;
}
static void undelete_obj(struct obj *obj, struct obj *prev)
{
if (prev) {
assert(obj->next == prev->next);
prev->next = obj;
} else {
assert(obj->next == obj->frame->objs);
obj->frame->objs = obj;
}
rereference_obj(obj);
}
/* ----- destroy/undelete interface ---------------------------------------- */
int destroy(void)
{
struct deletion *del;
if (!deletions)
return 0;
del = deletions;
switch (del->type) {
case dt_vec:
destroy_vec(del->u.vec.ref);
break;
case dt_obj:
destroy_obj(del->u.obj.ref);
break;
default:
abort();
}
deletions = del->next;
free(del);
return 1;
}
int undelete(void)
{
struct deletion *del;
if (!deletions)
return 0;
del = deletions;
switch (del->type) {
case dt_vec:
undelete_vec(del->u.vec.ref, del->u.vec.prev);
break;
case dt_obj:
undelete_obj(del->u.obj.ref, del->u.obj.prev);
break;
default:
abort();
}
deletions = del->next;
free(del);
return 1;
}

26
delete.h Normal file
View File

@ -0,0 +1,26 @@
/*
* delete.h - Object deletion
*
* Written 2009 by Werner Almesberger
* Copyright 2009 by Werner Almesberger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef DELETE_H
#define DELETE_H
#include "obj.h"
int delete_vec(struct vec *vec);
int delete_obj(struct obj *obj);
int destroy(void);
int undelete(void);
#endif /* !OBJ_H */

1
fpd.y
View File

@ -117,6 +117,7 @@ static struct obj *new_obj(enum obj_type type)
obj = alloc_type(struct obj);
obj->type = type;
obj->frame = curr_frame;
obj->next = NULL;
return obj;
}

View File

@ -13,8 +13,10 @@
#include <math.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include "obj.h"
#include "delete.h"
#include "inst.h"
#include "gui_inst.h"
#include "gui_style.h"
@ -29,6 +31,7 @@ static struct coord curr_pos;
static struct coord user_origin = { 0, 0 };
static int dragging = 0;
static int drag_escaped = 0; /* 1 once we've made is out of the drag radius */
static struct coord drag_start;
@ -111,9 +114,11 @@ static void drag_left(struct coord pos)
{
if (!dragging)
return;
if (hypot(pos.x-drag_start.x, pos.y-drag_start.y)/ctx.scale <
if (!drag_escaped &&
hypot(pos.x-drag_start.x, pos.y-drag_start.y)/ctx.scale <
DRAG_MIN_R)
return;
drag_escaped = 1;
tool_drag(&ctx, pos);
}
@ -159,6 +164,7 @@ static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event,
}
if (tool_consider_drag(&ctx, pos)) {
dragging = 1;
drag_escaped = 0;
drag_start = pos;
break;
}
@ -283,6 +289,16 @@ static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event,
ctx.center = pos;
redraw();
break;
case GDK_BackSpace:
case GDK_Delete:
case GDK_KP_Delete:
if (selected_inst && inst_delete(selected_inst))
change_world();
break;
case 'u':
if (undelete())
change_world();
break;
}
return TRUE;
}

13
inst.c
View File

@ -19,6 +19,7 @@
#include "coord.h"
#include "expr.h"
#include "obj.h"
#include "delete.h"
#include "gui_status.h"
#include "gui_tools.h"
#include "gui_inst.h"
@ -740,12 +741,13 @@ static struct inst_ops frame_ops = {
};
void inst_begin_frame(const struct frame *frame, struct coord base,
int active, int is_active_frame)
void inst_begin_frame(struct obj *obj, 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->obj = obj;
inst->u.frame.ref = frame;
inst->u.frame.active = is_active_frame;
inst->active = active;
@ -865,6 +867,13 @@ void inst_hover(struct inst *inst, struct draw_ctx *ctx, int on)
}
int inst_delete(struct inst *inst)
{
return inst->ops == &vec_ops ?
delete_vec(inst->vec) : delete_obj(inst->obj);
}
void inst_debug(void)
{
enum inst_prio prio;

5
inst.h
View File

@ -102,8 +102,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, int is_active_frame);
void inst_begin_frame(struct obj *obj, 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);
@ -117,6 +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_debug(void);
#endif /* !INST_H */

10
obj.c
View File

@ -33,7 +33,7 @@ struct frame *active_frame = NULL;
static int generate_frame(struct frame *frame, struct coord base,
const struct frame *parent, int active);
const struct frame *parent, struct obj *frame_ref, int active);
static struct num eval_unit(const struct expr *expr, const struct frame *frame)
@ -93,7 +93,7 @@ static int generate_objs(struct frame *frame, struct coord base, int active)
switch (obj->type) {
case ot_frame:
if (!generate_frame(obj->u.frame.ref,
obj->base ? obj->base->pos : base, frame,
obj->base ? obj->base->pos : base, frame, obj,
active && obj->u.frame.ref->active_ref == obj))
return 0;
break;
@ -237,14 +237,14 @@ static int iterate_tables(struct frame *frame, struct table *table,
static int generate_frame(struct frame *frame, struct coord base,
const struct frame *parent, int active)
const struct frame *parent, struct obj *frame_ref, int active)
{
int ok;
/*
* We ensure during construction that frames can never recurse.
*/
inst_begin_frame(frame, base,
inst_begin_frame(frame_ref, frame, base,
active && parent == active_frame,
active && frame == active_frame);
frame->curr_parent = parent;
@ -260,7 +260,7 @@ int instantiate(void)
int ok;
inst_start();
ok = generate_frame(root_frame, zero, NULL, 1);
ok = generate_frame(root_frame, zero, NULL, NULL, 1);
if (ok)
inst_commit();
else

11
obj.h
View File

@ -14,6 +14,7 @@
#ifndef OBJ_H
#define OBJ_H
#include <assert.h>
#include <gtk/gtk.h>
#include "expr.h"
@ -161,6 +162,7 @@ struct obj {
struct arc arc;
struct meas meas;
} u;
struct frame *frame;
struct vec *base;
struct obj *next;
int lineno;
@ -180,6 +182,15 @@ static inline struct vec *get_vec(struct vec *vec)
}
static inline void put_vec(struct vec *vec)
{
if (vec) {
assert(vec->n_refs);
vec->n_refs--;
}
}
int instantiate(void);
#endif /* !OBJ_H */