r5365 - developers/werner/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Sun Aug 2 07:17:40 CEST 2009


Author: werner
Date: 2009-08-02 07:17:39 +0200 (Sun, 02 Aug 2009)
New Revision: 5365

Modified:
   developers/werner/fped/TODO
   developers/werner/fped/gui_icons.c
   developers/werner/fped/gui_inst.c
   developers/werner/fped/inst.c
   developers/werner/fped/inst.h
Log:
- implemented radio buttons for icon bar, but don't like them
- removed excessive paranoia in inst_get_bbox
- instances are now stacked by drawing/selection priority
- struct inst_ops is only used inside inst.c, moved it there
- no longer need "magic" VEC_EYE_R in gui_inst.c to give vectors selection 
  priority
- when selecting an arc now only consider the part drawn, not the whole circle



Modified: developers/werner/fped/TODO
===================================================================
--- developers/werner/fped/TODO	2009-08-01 23:12:30 UTC (rev 5364)
+++ developers/werner/fped/TODO	2009-08-02 05:17:39 UTC (rev 5365)
@@ -16,13 +16,9 @@
 - detect recursive evaluation (through variables)
 - eliminate duplicate instances
 
-Bugs:
-- when selecting an arc only consider the part drawn, not the whole circle
-
 Style:
-- stack elements (1): frames, pads, silk, vecs
-- stack elements (2): all unselected below all selected
-- stack elements (3): circle on top of vec
+- stack elements (2a): all inactive below all active
+- stack elements (2b): unselected below selected
 - make column of entry field greedily consume all unallocated space
 
 Code cleanup:

Modified: developers/werner/fped/gui_icons.c
===================================================================
--- developers/werner/fped/gui_icons.c	2009-08-01 23:12:30 UTC (rev 5364)
+++ developers/werner/fped/gui_icons.c	2009-08-02 05:17:39 UTC (rev 5365)
@@ -28,8 +28,8 @@
 #include "icons/vec.xpm"
 
 
-static GtkWidget *icon_button(GtkWidget *bar, GdkDrawable *drawable,
-     char **xpm)
+static GtkToolItem *icon_button(GtkWidget *bar, GdkDrawable *drawable,
+     char **xpm, GtkToolItem *last)
 {
 	GdkPixmap *pixmap;
 	GtkWidget *image;	
@@ -38,19 +38,34 @@
 	pixmap = gdk_pixmap_create_from_xpm_d(drawable, NULL, NULL, xpm);
 	image = gtk_image_new_from_pixmap(pixmap, NULL);
 
+/*
+ * gtk_radio_tool_button_new_from_widget is *huge*. we try to do things in a
+ * more compact way.
+ */
+#if 0
+	if (last)
+		item = gtk_radio_tool_button_new_from_widget(
+		    GTK_RADIO_TOOL_BUTTON(last));
+	else
+		item = gtk_radio_tool_button_new(NULL);
+	gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(item), image);
+#else
 	item = gtk_tool_item_new();
 	gtk_container_add(GTK_CONTAINER(item), image);
 
 	gtk_container_set_border_width(GTK_CONTAINER(item), 1);
+#endif
+
 	gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1);
 
-	return NULL;
+	return item;
 }
 
 
 GtkWidget *gui_setup_icons(GdkDrawable *drawable)
 {
 	GtkWidget *bar;
+	GtkToolItem *last;
 
 	bar = gtk_toolbar_new();
 	gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS);
@@ -58,15 +73,15 @@
 	    GTK_ORIENTATION_VERTICAL);
 //gtk_container_set_border_width(GTK_CONTAINER(bar), 5);
 
-	icon_button(bar, drawable, xpm_point);
-	icon_button(bar, drawable, xpm_vec);
-	icon_button(bar, drawable, xpm_frame);
-	icon_button(bar, drawable, xpm_pad);
-	icon_button(bar, drawable, xpm_line);
-	icon_button(bar, drawable, xpm_rect);
-	icon_button(bar, drawable, xpm_circ);
-	icon_button(bar, drawable, xpm_arc);
-	icon_button(bar, drawable, xpm_meas);
+	last = icon_button(bar, drawable, xpm_point, NULL);
+	last = icon_button(bar, drawable, xpm_vec, last);
+	last = icon_button(bar, drawable, xpm_frame, last);
+	last = icon_button(bar, drawable, xpm_pad, last);
+	last = icon_button(bar, drawable, xpm_line, last);
+	last = icon_button(bar, drawable, xpm_rect, last);
+	last = icon_button(bar, drawable, xpm_circ, last);
+	last = icon_button(bar, drawable, xpm_arc, last);
+	last = icon_button(bar, drawable, xpm_meas, last);
 
 	return bar;
 }

Modified: developers/werner/fped/gui_inst.c
===================================================================
--- developers/werner/fped/gui_inst.c	2009-08-01 23:12:30 UTC (rev 5364)
+++ developers/werner/fped/gui_inst.c	2009-08-02 05:17:39 UTC (rev 5365)
@@ -164,7 +164,7 @@
 	unit_type d;
 
 	d = dist_line(pos, self->bbox.min, self->bbox.max)/scale;
-	return d > SELECT_R ? -1 : d+VEC_EYE_R;
+	return d > SELECT_R ? -1 : d;
 }
 
 
@@ -187,7 +187,7 @@
 	unit_type d;
 
 	d = dist_rect(pos, self->bbox.min, self->bbox.max)/scale;
-	return d > SELECT_R ? -1 : d+VEC_EYE_R;
+	return d > SELECT_R ? -1 : d;
 }
 
 
@@ -211,9 +211,9 @@
 	unit_type d;
 
 	if (inside_rect(pos, self->bbox.min, self->bbox.max))
-		return VEC_EYE_R;
+		return SELECT_R;
 	d = dist_rect(pos, self->bbox.min, self->bbox.max)/scale;
-	return d > SELECT_R ? -1 : d+VEC_EYE_R;
+	return d > SELECT_R ? -1 : d;
 }
 
 
@@ -233,12 +233,54 @@
 /* ----- arc --------------------------------------------------------------- */
 
 
+static struct coord rotate_r(struct coord center, unit_type r, double angle)
+{
+	struct coord res;
+
+	angle = angle/180.0*M_PI;
+	res.x = center.x+r*cos(angle);
+	res.y = center.y+r*sin(angle);
+	return res;
+}
+
+
 unit_type gui_dist_arc(struct inst *self, struct coord pos, unit_type scale)
 {
-	unit_type d;
+	struct coord c = self->base;
+	struct coord p;
+	unit_type d_min, d;
+	double angle, a2;
 
-	d = dist_circle(pos, self->base, self->u.arc.r)/scale;
-	return d > SELECT_R ? -1 : d+VEC_EYE_R;
+	/* check endpoints */
+
+	p = rotate_r(c, self->u.arc.r, self->u.arc.a1);
+	d_min = hypot(pos.x-p.x, pos.y-p.y);
+
+	p = rotate_r(c, self->u.arc.r, self->u.arc.a2);
+	d = hypot(pos.x-p.x, pos.y-p.y);
+        if (d < d_min)
+                d_min = d;
+
+	if (d_min/scale <= SELECT_R)
+		return d;
+
+	/* distance from the circle containing the arc */
+
+	d = dist_circle(pos, c, self->u.arc.r)/scale;
+	if (d > SELECT_R)
+		return -1;
+	if (self->u.arc.a1 == self->u.arc.a2)
+		return d;
+
+	/* see if we're close to the part that's actually drawn */
+
+	angle = atan2(pos.y-c.y, pos.x-c.x)/M_PI*180.0;
+	if (angle < 0)
+		angle += 180;
+	a2 = self->u.arc.a2;
+	if (a2 < self->u.arc.a1)
+		a2 += 180;
+	return angle >= self->u.arc.a1 && angle <= a2 ? d : -1;
 }
 
 
@@ -283,7 +325,7 @@
 	a = add_vec(self->base, off);
 	b = add_vec(self->u.meas.end, off);
 	d = dist_line(pos, a, b)/scale;
-	return d > SELECT_R ? -1 : d+VEC_EYE_R;
+	return d > SELECT_R ? -1 : d;
 }
 
 

Modified: developers/werner/fped/inst.c
===================================================================
--- developers/werner/fped/inst.c	2009-08-01 23:12:30 UTC (rev 5364)
+++ developers/werner/fped/inst.c	2009-08-02 05:17:39 UTC (rev 5365)
@@ -24,11 +24,48 @@
 #include "inst.h"
 
 
+struct inst_ops {
+	void (*debug)(struct inst *self);
+	void (*save)(FILE *file, struct inst *self);
+	void (*draw)(struct inst *self, struct draw_ctx *ctx);
+	unit_type (*distance)(struct inst *self, struct coord pos, 
+            unit_type scale);
+	void (*select)(struct inst *self);
+};
+
+enum inst_prio {
+	ip_frame,	/* frames have their own selection */
+	ip_pad,		/* pads also accept clicks inside */
+	ip_circ,	/* circles don't overlap easily */
+	ip_arc,		/* arc are like circles, just shorter */
+	ip_rect,	/* rectangles have plenty of sides */
+	ip_meas,	/* mesurements are like lines but set a bit apart */
+	ip_line,	/* lines are easly overlapped by other things */
+	ip_vec,		/* vectors only have the end point */
+	ip_n,		/* number of priorities */
+};
+
+
+#define FOR_INST_PRIOS_UP(prio)					\
+	for (prio = 0; prio != ip_n; prio++)
+
+#define FOR_INST_PRIOS_DOWN(prio)				\
+	for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--)
+
+#define	FOR_INSTS_UP(prio, inst)				\
+	FOR_INST_PRIOS_UP(prio)					\
+		for (inst = insts[prio]; inst; inst = inst->next)
+
+#define	FOR_INSTS_DOWN(prio, inst)				\
+	FOR_INST_PRIOS_DOWN(prio)				\
+		for (inst = insts[prio]; inst; inst = inst->next)
+
+
 struct inst *curr_frame = NULL;
 struct inst *selected_inst = NULL;
 
-static struct inst *insts = NULL, **next_inst;
-static struct inst *prev_insts;
+static struct inst *insts[ip_n], **next_inst[ip_n];
+static struct inst *prev_insts[ip_n];
 
 static unsigned long active_set = 0;
 
@@ -86,27 +123,31 @@
 
 int inst_select(const struct draw_ctx *ctx, struct coord pos)
 {
+	enum inst_prio prio;
 	struct inst *inst;
 	int best_dist, dist;
 
 	deselect_outside();
-	selected_inst = NULL;
 	edit_nothing();
-	for (inst = insts; inst; inst = inst->next) {
-		if (!inst->active || !inst->ops->distance)
-			continue;
-		dist = inst->ops->distance(inst, pos, ctx->scale);
-		if (dist >= 0 && (!selected_inst || best_dist > dist)) {
-			selected_inst = inst;
-			best_dist = dist;
+	FOR_INST_PRIOS_DOWN(prio) {
+		selected_inst = NULL;
+		for (inst = insts[prio]; inst; inst = inst->next) {
+			if (!inst->active || !inst->ops->distance)
+				continue;
+			dist = inst->ops->distance(inst, pos, ctx->scale);
+			if (dist >= 0 && (!selected_inst || best_dist > dist)) {
+				selected_inst = inst;
+				best_dist = dist;
+			}
 		}
+		if (selected_inst) {
+			set_path(1);
+			if (selected_inst->ops->select)
+				selected_inst->ops->select(selected_inst);
+			return 1;
+		}
 	}
-	if (selected_inst) {
-		set_path(1);
-		if (selected_inst->ops->select)
-			selected_inst->ops->select(selected_inst);
-	}
-	return selected_inst != NULL;
+	return 0;
 }
 
 
@@ -165,7 +206,8 @@
 	update_bbox(&curr_frame->bbox, inst->bbox.max);
 }
 
-static struct inst *add_inst(const struct inst_ops *ops, struct coord base)
+static struct inst *add_inst(const struct inst_ops *ops, enum inst_prio prio,
+    struct coord base)
 {
 	struct inst *inst;
 
@@ -176,8 +218,8 @@
 	inst->active = IS_ACTIVE;
 	inst->in_path = 0;
 	inst->next = NULL;
-	*next_inst = inst;
-	next_inst = &inst->next;
+	*next_inst[prio] = inst;
+	next_inst[prio] = &inst->next;
 	return inst;
 }
 
@@ -227,7 +269,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&vec_ops, base);
+	inst = add_inst(&vec_ops, ip_vec, base);
 	inst->vec = vec;
 	inst->u.end = vec->pos;
 	update_bbox(&inst->bbox, vec->pos);
@@ -265,7 +307,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&line_ops, a);
+	inst = add_inst(&line_ops, ip_line, a);
 	inst->obj = obj;
 	inst->u.end = b;
 	update_bbox(&inst->bbox, b);
@@ -303,7 +345,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&rect_ops, a);
+	inst = add_inst(&rect_ops, ip_rect, a);
 	inst->obj = obj;
 	inst->u.end = b;
 	update_bbox(&inst->bbox, b);
@@ -355,7 +397,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&pad_ops, a);
+	inst = add_inst(&pad_ops, ip_pad, a);
 	inst->obj = obj;
 	inst->u.name = stralloc(name);
 	update_bbox(&inst->bbox, b);
@@ -399,7 +441,7 @@
 	struct inst *inst;
 	double r, a1, a2;
 
-	inst = add_inst(&arc_ops, center);
+	inst = add_inst(&arc_ops, ip_arc, center);
 	inst->obj = obj;
 	r = hypot(start.x-center.x, start.y-center.y);
 	a1 = atan2(start.y-center.y, start.x-center.x)/M_PI*180.0;
@@ -452,7 +494,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&meas_ops, from);
+	inst = add_inst(&meas_ops, ip_meas, from);
 	inst->obj = obj;
 	inst->u.meas.end = to;
 	inst->u.meas.offset = offset;
@@ -499,7 +541,7 @@
 {
 	struct inst *inst;
 
-	inst = add_inst(&frame_ops, base);
+	inst = add_inst(&frame_ops, ip_frame, base);
 	inst->u.frame.ref = frame;
 	inst->active = active;
 	curr_frame = inst;
@@ -521,29 +563,33 @@
 
 struct bbox inst_get_bbox(void)
 {
-	static struct bbox bbox_zero;
-
-	return insts ? insts->bbox : bbox_zero;
+	return insts[ip_frame]->bbox;
 }
 
 
-static void inst_free(struct inst *list)
+static void inst_free(struct inst *list[ip_n])
 {
+	enum inst_prio prio;
 	struct inst *next;
 
-	while (list) {
-		next = list->next;
-		free(list);
-		list = next;
-	}
+	FOR_INST_PRIOS_UP(prio)
+		while (list[prio]) {
+			next = list[prio]->next;
+			free(list[prio]);
+			list[prio] = next;
+		}
 }
 
 
 void inst_start(void)
 {
-	prev_insts = insts;
-	insts = NULL;
-	next_inst = &insts;
+	enum inst_prio prio;
+
+	FOR_INST_PRIOS_UP(prio) {
+		prev_insts[prio] = insts[prio];
+		insts[prio] = NULL;
+		next_inst[prio] = &insts[prio];
+	}
 }
 
 
@@ -555,25 +601,30 @@
 
 void inst_revert(void)
 {
+	enum inst_prio prio;
+
 	inst_free(insts);
-	insts = prev_insts;
+	FOR_INST_PRIOS_UP(prio)
+		insts[prio] = prev_insts[prio];
 }
 
 
 void inst_draw(struct draw_ctx *ctx)
 {
-	struct inst *walk;
+	enum inst_prio prio;
+	struct inst *inst;
 
-	for (walk = insts; walk; walk = walk->next)
-		if (walk->ops->draw)
-			walk->ops->draw(walk, ctx);
+	FOR_INSTS_UP(prio, inst)
+		if (inst->ops->draw)
+			inst->ops->draw(inst, ctx);
 }
 
 
 void inst_debug(void)
 {
-	struct inst *walk;
+	enum inst_prio prio;
+	struct inst *inst;
 
-	for (walk = insts; walk; walk = walk->next)
-		walk->ops->debug(walk);
+	FOR_INSTS_UP(prio, inst)
+		inst->ops->debug(inst);
 }

Modified: developers/werner/fped/inst.h
===================================================================
--- developers/werner/fped/inst.h	2009-08-01 23:12:30 UTC (rev 5364)
+++ developers/werner/fped/inst.h	2009-08-02 05:17:39 UTC (rev 5365)
@@ -34,18 +34,9 @@
 	struct coord max;
 };
 
-struct inst;
+struct inst_ops;
 struct draw_ctx;
 
-struct inst_ops {
-	void (*debug)(struct inst *self);
-	void (*save)(FILE *file, struct inst *self);
-	void (*draw)(struct inst *self, struct draw_ctx *ctx);
-	unit_type (*distance)(struct inst *self, struct coord pos, 
-            unit_type scale);
-	void (*select)(struct inst *self);
-};
-
 struct inst {
 	const struct inst_ops *ops;
 	struct coord base;




More information about the commitlog mailing list