mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-22 07:30:16 +02: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:
parent
5d7ab083a3
commit
3db91b5c1b
2
Makefile
2
Makefile
@ -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
4
README
@ -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
2
TODO
@ -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
286
delete.c
Normal 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
26
delete.h
Normal 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
1
fpd.y
@ -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;
|
||||
}
|
||||
|
18
gui_canvas.c
18
gui_canvas.c
@ -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
13
inst.c
@ -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
5
inst.h
@ -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
10
obj.c
@ -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
11
obj.h
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user