diff --git a/Makefile b/Makefile index 54b1b27..f109b04 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ unparse.o dump.o meas.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 \ - gui_tools.o + gui_tools.o gui_over.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 meas_x.xpm meas_y.xpm diff --git a/gui_canvas.c b/gui_canvas.c index c83be41..182ad10 100644 --- a/gui_canvas.c +++ b/gui_canvas.c @@ -18,6 +18,7 @@ #include "obj.h" #include "delete.h" #include "inst.h" +#include "gui_util.h" #include "gui_inst.h" #include "gui_style.h" #include "gui_status.h" @@ -26,9 +27,8 @@ #include "gui_canvas.h" -void (*highlight)(struct draw_ctx *ctx) = NULL; +void (*highlight)(void) = NULL; -static struct draw_ctx ctx; static struct coord curr_pos; static struct coord user_origin = { 0, 0 }; @@ -42,7 +42,7 @@ static struct coord drag_start; static void update_zoom(void) { - status_set_zoom("x%d", ctx.scale); + status_set_zoom("x%d", draw_ctx.scale); } @@ -63,8 +63,8 @@ static void center(const struct bbox *this_bbox) struct bbox bbox; bbox = this_bbox ? *this_bbox : inst_get_bbox(); - ctx.center.x = (bbox.min.x+bbox.max.x)/2; - ctx.center.y = (bbox.min.y+bbox.max.y)/2; + draw_ctx.center.x = (bbox.min.x+bbox.max.x)/2; + draw_ctx.center.y = (bbox.min.y+bbox.max.y)/2; } @@ -76,8 +76,8 @@ static void auto_scale(const struct bbox *this_bbox) float aw, ah; bbox = this_bbox ? *this_bbox : inst_get_bbox(); - aw = ctx.widget->allocation.width; - ah = ctx.widget->allocation.height; + aw = draw_ctx.widget->allocation.width; + ah = draw_ctx.widget->allocation.height; h = bbox.max.x-bbox.min.x; w = bbox.max.y-bbox.min.y; aw -= 2*CANVAS_CLEARANCE; @@ -88,7 +88,7 @@ static void auto_scale(const struct bbox *this_bbox) ah = 1; sx = ceil(h/aw); sy = ceil(w/ah); - ctx.scale = sx > sy ? sx : sy > 0 ? sy : 1; + draw_ctx.scale = sx > sy ? sx : sy > 0 ? sy : 1; update_zoom(); } @@ -101,15 +101,15 @@ void redraw(void) { float aw, ah; - aw = ctx.widget->allocation.width; - ah = ctx.widget->allocation.height; - gdk_draw_rectangle(ctx.widget->window, + aw = draw_ctx.widget->allocation.width; + ah = draw_ctx.widget->allocation.height; + gdk_draw_rectangle(draw_ctx.widget->window, instantiation_ok ? gc_bg : gc_bg_error, TRUE, 0, 0, aw, ah); - inst_draw(&ctx); + inst_draw(); if (highlight) - highlight(&ctx); - tool_redraw(&ctx); + highlight(); + tool_redraw(); } @@ -121,11 +121,11 @@ static void drag_left(struct coord pos) if (!dragging) return; if (!drag_escaped && - hypot(pos.x-drag_start.x, pos.y-drag_start.y)/ctx.scale < + hypot(pos.x-drag_start.x, pos.y-drag_start.y)/draw_ctx.scale < DRAG_MIN_R) return; drag_escaped = 1; - tool_drag(&ctx, pos); + tool_drag(pos); } @@ -137,14 +137,13 @@ static void drag_middle(struct coord pos) static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { - struct coord pos = canvas_to_coord(&ctx, event->x, event->y); + struct coord pos = canvas_to_coord(event->x, event->y); curr_pos.x = event->x; curr_pos.y = event->y; + tool_hover(pos); if (event->state & GDK_BUTTON1_MASK) drag_left(pos); - else - tool_hover(&ctx, pos); if (event->state & GDK_BUTTON2_MASK) drag_middle(pos); update_pos(pos); @@ -158,7 +157,7 @@ static gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - struct coord pos = canvas_to_coord(&ctx, event->x, event->y); + struct coord pos = canvas_to_coord(event->x, event->y); const struct inst *prev; int res; @@ -166,10 +165,10 @@ static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, case 1: if (dragging) { fprintf(stderr, "HUH ?!?\n"); - tool_cancel_drag(&ctx); + tool_cancel_drag(); dragging = 0; } - res = tool_consider_drag(&ctx, pos); + res = tool_consider_drag(pos); /* tool doesn't do drag */ if (res < 0) { change_world(); @@ -186,12 +185,12 @@ static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, } prev = selected_inst; inst_deselect(); - inst_select(&ctx, pos); + inst_select(pos); if (prev != selected_inst) redraw(); break; case 2: - ctx.center = pos; + draw_ctx.center = pos; redraw(); break; } @@ -202,18 +201,18 @@ static gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - struct coord pos = canvas_to_coord(&ctx, event->x, event->y); + struct coord pos = canvas_to_coord(event->x, event->y); switch (event->button) { case 1: if (!dragging) break; dragging = 0; - if (hypot(pos.x-drag_start.x, pos.y-drag_start.y)/ctx.scale < - DRAG_MIN_R) - tool_cancel_drag(&ctx); + if (hypot(pos.x-drag_start.x, + pos.y-drag_start.y)/draw_ctx.scale < DRAG_MIN_R) + tool_cancel_drag(); else { - if (tool_end_drag(&ctx, pos)) + if (tool_end_drag(pos)) change_world(); } break; @@ -227,11 +226,11 @@ static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, static void zoom_in(struct coord pos) { - if (ctx.scale < 2) + if (draw_ctx.scale < 2) return; - ctx.scale /= 2; - ctx.center.x = (ctx.center.x+pos.x)/2; - ctx.center.y = (ctx.center.y+pos.y)/2; + draw_ctx.scale /= 2; + draw_ctx.center.x = (draw_ctx.center.x+pos.x)/2; + draw_ctx.center.y = (draw_ctx.center.y+pos.y)/2; update_zoom(); redraw(); } @@ -242,16 +241,16 @@ static void zoom_out(struct coord pos) struct bbox bbox; bbox = inst_get_bbox(); - bbox.min = translate(&ctx, bbox.min); - bbox.max = translate(&ctx, bbox.max); + bbox.min = translate(bbox.min); + bbox.max = translate(bbox.max); if (bbox.min.x >= ZOOM_STOP_BORDER && bbox.max.y >= ZOOM_STOP_BORDER && - bbox.max.x < ctx.widget->allocation.width-ZOOM_STOP_BORDER && - bbox.min.y < ctx.widget->allocation.height-ZOOM_STOP_BORDER) + bbox.max.x < draw_ctx.widget->allocation.width-ZOOM_STOP_BORDER && + bbox.min.y < draw_ctx.widget->allocation.height-ZOOM_STOP_BORDER) return; - ctx.scale *= 2; - ctx.center.x = 2*ctx.center.x-pos.x; - ctx.center.y = 2*ctx.center.y-pos.y; + draw_ctx.scale *= 2; + draw_ctx.center.x = 2*draw_ctx.center.x-pos.x; + draw_ctx.center.y = 2*draw_ctx.center.y-pos.y; update_zoom(); redraw(); } @@ -260,7 +259,7 @@ static void zoom_out(struct coord pos) static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data) { - struct coord pos = canvas_to_coord(&ctx, event->x, event->y); + struct coord pos = canvas_to_coord(event->x, event->y); switch (event->direction) { case GDK_SCROLL_UP: @@ -282,7 +281,7 @@ static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { - struct coord pos = canvas_to_coord(&ctx, curr_pos.x, curr_pos.y); + struct coord pos = canvas_to_coord(curr_pos.x, curr_pos.y); switch (event->keyval) { case ' ': @@ -307,7 +306,7 @@ static gboolean key_press_event(GtkWidget *widget, GdkEventKey *event, redraw(); break; case '.': - ctx.center = pos; + draw_ctx.center = pos; redraw(); break; case GDK_BackSpace: @@ -361,8 +360,8 @@ static gboolean leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer data) { if (dragging) - tool_cancel_drag(&ctx); - tool_dehover(&ctx); + tool_cancel_drag(); + tool_dehover(); dragging = 0; return TRUE; } @@ -422,7 +421,7 @@ GtkWidget *make_canvas(void) GDK_SCROLL | GDK_POINTER_MOTION_MASK); - ctx.widget = canvas; + draw_ctx.widget = canvas; return canvas; } diff --git a/gui_canvas.h b/gui_canvas.h index 84031e7..64a15a8 100644 --- a/gui_canvas.h +++ b/gui_canvas.h @@ -22,7 +22,7 @@ * of objects. */ -extern void (*highlight)(struct draw_ctx *ctx); +extern void (*highlight)(void); void redraw(void); diff --git a/gui_inst.c b/gui_inst.c index 1fdf05f..fd3f27e 100644 --- a/gui_inst.c +++ b/gui_inst.c @@ -24,35 +24,31 @@ #include "gui_inst.h" -#define DA GDK_DRAWABLE(ctx->widget->window) - - /* ----- coordinate translation -------------------------------------------- */ -struct coord translate(const struct draw_ctx *ctx, struct coord pos) +struct coord translate(struct coord pos) { - pos.x -= ctx->center.x; - pos.y -= ctx->center.y; - pos.x /= ctx->scale; - pos.y /= ctx->scale; + pos.x -= draw_ctx.center.x; + pos.y -= draw_ctx.center.y; + pos.x /= draw_ctx.scale; + pos.y /= draw_ctx.scale; pos.y = -pos.y; - pos.x += ctx->widget->allocation.width/2; - pos.y += ctx->widget->allocation.height/2; -//fprintf(stderr, "%d %d\n", (int) pos.x, (int) pos.y); + pos.x += draw_ctx.widget->allocation.width/2; + pos.y += draw_ctx.widget->allocation.height/2; return pos; } -struct coord canvas_to_coord(const struct draw_ctx *ctx, int x, int y) +struct coord canvas_to_coord(int x, int y) { struct coord pos; - x -= ctx->widget->allocation.width/2; - y -= ctx->widget->allocation.height/2; + x -= draw_ctx.widget->allocation.width/2; + y -= draw_ctx.widget->allocation.height/2; y = -y; - pos.x = x*ctx->scale+ctx->center.x; - pos.y = y*ctx->scale+ctx->center.y; + pos.x = x*draw_ctx.scale+draw_ctx.center.x; + pos.y = y*draw_ctx.scale+draw_ctx.center.y; return pos; } @@ -60,8 +56,7 @@ struct coord canvas_to_coord(const struct draw_ctx *ctx, int x, int y) /* ----- drawing primitives ------------------------------------------------ */ -static void draw_eye(struct draw_ctx *ctx, GdkGC *gc, struct coord center, - int r1, int r2) +static void draw_eye(GdkGC *gc, struct coord center, int r1, int r2) { draw_circle(DA, gc, TRUE, center.x, center.y, r1); draw_circle(DA, gc, FALSE, center.x, center.y, r2); @@ -71,7 +66,7 @@ static void draw_eye(struct draw_ctx *ctx, GdkGC *gc, struct coord center, #define MAX_POINTS 10 -static void draw_poly(struct draw_ctx *ctx, GdkGC *gc, int fill, +static void draw_poly(GdkGC *gc, int fill, const struct coord *points, int n_points) { GdkPoint gp[MAX_POINTS]; @@ -92,7 +87,7 @@ static void draw_poly(struct draw_ctx *ctx, GdkGC *gc, int fill, } -static void draw_arrow(struct draw_ctx *ctx, GdkGC *gc, int fill, +static void draw_arrow(GdkGC *gc, int fill, struct coord from, struct coord to, int len, double angle) { struct coord p[3]; @@ -107,7 +102,7 @@ static void draw_arrow(struct draw_ctx *ctx, GdkGC *gc, int fill, p[0] = add_vec(to, rotate(side, 180-angle)); p[1] = to; p[2] = add_vec(to, rotate(side, 180+angle)); - draw_poly(ctx, gc, fill, p, 3); + draw_poly(gc, fill, p, 3); } @@ -149,32 +144,22 @@ unit_type gui_dist_vec_fallback(struct inst *self, struct coord pos, } -void gui_hover_vec(struct inst *self, struct draw_ctx *ctx) +void gui_highlight_vec(struct inst *self) { - struct coord center = translate(ctx, self->u.rect.end); - GdkGC *gc; - - gc = gc_vec[mode_hover]; - draw_circle(DA, gc, FALSE, center.x, center.y, VEC_EYE_R); -} - - -void gui_highlight_vec(struct inst *self, struct draw_ctx *ctx) -{ - struct coord center = translate(ctx, self->u.rect.end); + struct coord center = translate(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) +void gui_draw_vec(struct inst *self) { - struct coord from = translate(ctx, self->base); - struct coord to = translate(ctx, self->u.rect.end); + struct coord from = translate(self->base); + struct coord to = translate(self->u.rect.end); GdkGC *gc; gc = gc_vec[get_mode(self)]; - draw_arrow(ctx, gc, TRUE, from, to, VEC_ARROW_LEN, VEC_ARROW_ANGLE); + draw_arrow(gc, TRUE, from, to, VEC_ARROW_LEN, VEC_ARROW_ANGLE); gdk_draw_line(DA, gc, from.x, from.y, to.x, to.y); draw_circle(DA, gc, FALSE, to.x, to.y, VEC_EYE_R); } @@ -195,14 +180,14 @@ unit_type gui_dist_line(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_line(struct inst *self, struct draw_ctx *ctx) +void gui_draw_line(struct inst *self) { - struct coord min = translate(ctx, self->base); - struct coord max = translate(ctx, self->u.rect.end); + struct coord min = translate(self->base); + struct coord max = translate(self->u.rect.end); GdkGC *gc; gc = gc_obj[get_mode(self)]; - set_width(gc, self->u.rect.width/ctx->scale); + set_width(gc, self->u.rect.width/draw_ctx.scale); gdk_draw_line(DA, gc, min.x, min.y, max.x, max.y); } @@ -222,15 +207,15 @@ unit_type gui_dist_rect(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_rect(struct inst *self, struct draw_ctx *ctx) +void gui_draw_rect(struct inst *self) { - struct coord min = translate(ctx, self->base); - struct coord max = translate(ctx, self->u.rect.end); + struct coord min = translate(self->base); + struct coord max = translate(self->u.rect.end); GdkGC *gc; sort_coord(&min, &max); gc = gc_obj[get_mode(self)]; - set_width(gc, self->u.rect.width/ctx->scale); + set_width(gc, self->u.rect.width/draw_ctx.scale); gdk_draw_rectangle(DA, gc, FALSE, min.x, min.y, max.x-min.x, max.y-min.y); } @@ -250,10 +235,10 @@ unit_type gui_dist_pad(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_pad(struct inst *self, struct draw_ctx *ctx) +void gui_draw_pad(struct inst *self) { - struct coord min = translate(ctx, self->base); - struct coord max = translate(ctx, self->u.pad.other); + struct coord min = translate(self->base); + struct coord max = translate(self->u.pad.other); GdkGC *gc; struct coord c; unit_type h, w; @@ -323,15 +308,15 @@ unit_type gui_dist_arc(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_arc(struct inst *self, struct draw_ctx *ctx) +void gui_draw_arc(struct inst *self) { - struct coord center = translate(ctx, self->base); + struct coord center = translate(self->base); GdkGC *gc; gc = gc_obj[get_mode(self)]; - set_width(gc, self->u.arc.width/ctx->scale); + set_width(gc, self->u.arc.width/draw_ctx.scale); draw_arc(DA, gc, FALSE, center.x, center.y, - self->u.arc.r/ctx->scale, self->u.arc.a1, self->u.arc.a2); + self->u.arc.r/draw_ctx.scale, self->u.arc.a1, self->u.arc.a2); } @@ -368,7 +353,7 @@ unit_type gui_dist_meas(struct inst *self, struct coord pos, unit_type scale) } -void gui_draw_meas(struct inst *self, struct draw_ctx *ctx) +void gui_draw_meas(struct inst *self) { struct coord a0, b0, a1, b1, off, c, d; GdkGC *gc; @@ -377,8 +362,8 @@ void gui_draw_meas(struct inst *self, struct draw_ctx *ctx) self->u.meas.meas->label ? self->u.meas.meas->label : "" : ""; char *s; - a0 = translate(ctx, self->base); - b0 = translate(ctx, self->u.meas.end); + a0 = translate(self->base); + b0 = translate(self->u.meas.end); a1 = self->base; b1 = self->u.meas.end; switch (self->u.meas.meas ? self->u.meas.meas->type : mt_xy_next) { @@ -398,14 +383,14 @@ void gui_draw_meas(struct inst *self, struct draw_ctx *ctx) } off = offset_vec(a1, b1, self); len = units_to_mm(dist_point(a1, b1)); - a1 = translate(ctx, add_vec(a1, off)); - b1 = translate(ctx, add_vec(b1, off)); + a1 = translate(add_vec(a1, off)); + b1 = translate(add_vec(b1, off)); gc = gc_meas[get_mode(self)]; gdk_draw_line(DA, gc, a0.x, a0.y, a1.x, a1.y); gdk_draw_line(DA, gc, b0.x, b0.y, b1.x, b1.y); gdk_draw_line(DA, gc, a1.x, a1.y, b1.x, b1.y); - draw_arrow(ctx, gc, FALSE, a1, b1, MEAS_ARROW_LEN, MEAS_ARROW_ANGLE); - draw_arrow(ctx, gc, FALSE, b1, a1, MEAS_ARROW_LEN, MEAS_ARROW_ANGLE); + draw_arrow(gc, FALSE, a1, b1, MEAS_ARROW_LEN, MEAS_ARROW_ANGLE); + draw_arrow(gc, FALSE, b1, a1, MEAS_ARROW_LEN, MEAS_ARROW_ANGLE); c = add_vec(a1, b1); d = sub_vec(b1, a1); @@ -464,27 +449,17 @@ unit_type gui_dist_frame(struct inst *self, struct coord pos, unit_type scale) } -void gui_hover_frame(struct inst *self, struct draw_ctx *ctx) +void gui_draw_frame(struct inst *self) { - struct coord center = translate(ctx, self->base); - GdkGC *gc; - - gc = gc_frame[mode_hover]; - draw_circle(DA, gc, FALSE, center.x, center.y, FRAME_EYE_R2); -} - - -void gui_draw_frame(struct inst *self, struct draw_ctx *ctx) -{ - struct coord center = translate(ctx, self->base); + struct coord center = translate(self->base); struct coord corner = { self->bbox.min.x, self->bbox.max.y }; GdkGC *gc; gc = self->u.frame.active ? gc_active_frame : gc_frame[get_mode(self)]; - draw_eye(ctx, gc, center, FRAME_EYE_R1, FRAME_EYE_R2); + draw_eye(gc, center, FRAME_EYE_R1, FRAME_EYE_R2); if (!self->u.frame.ref->name) return; - corner = translate(ctx, corner); + corner = translate(corner); corner.x -= FRAME_CLEARANCE; corner.y -= FRAME_CLEARANCE; gdk_draw_line(DA, gc, corner.x, corner.y, diff --git a/gui_inst.h b/gui_inst.h index ca67c43..55a95c2 100644 --- a/gui_inst.h +++ b/gui_inst.h @@ -20,15 +20,8 @@ #include "inst.h" -struct draw_ctx { - GtkWidget *widget; - int scale; - struct coord center; -}; - - -struct coord translate(const struct draw_ctx *ctx, struct coord pos); -struct coord canvas_to_coord(const struct draw_ctx *ctx, int x, int y); +struct coord translate(struct coord pos); +struct coord canvas_to_coord(int x, int y); unit_type gui_dist_vec(struct inst *self, struct coord pos, unit_type scale); unit_type gui_dist_vec_fallback(struct inst *self, struct coord pos, @@ -42,16 +35,14 @@ 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); -void gui_draw_rect(struct inst *self, struct draw_ctx *ctx); -void gui_draw_pad(struct inst *self, struct draw_ctx *ctx); -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_draw_vec(struct inst *self); +void gui_draw_line(struct inst *self); +void gui_draw_rect(struct inst *self); +void gui_draw_pad(struct inst *self); +void gui_draw_arc(struct inst *self); +void gui_draw_meas(struct inst *self); +void gui_draw_frame(struct inst *self); -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); +void gui_highlight_vec(struct inst *self); #endif /* !GUI_INST_H */ diff --git a/gui_over.c b/gui_over.c new file mode 100644 index 0000000..b210ca2 --- /dev/null +++ b/gui_over.c @@ -0,0 +1,211 @@ +/* + * gui_over.c - GUI, canvas overlays + * + * 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. + */ + +/* + * This file is for the overlay state machine only. Given the heavy use of + * global variables, adding other functionality would quickly render it + * illegible. + */ + + +#include +#include + +#include "coord.h" +#include "gui_util.h" +#include "gui_over.h" + + +#if 0 +#define DPRINTF(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) +#else +#define DPRINTF(fmt, ...) +#endif + + +static enum states { + NOTHING, + HOVER, + DRAG, + BOTH, +} state = NOTHING; + + +/* + * We cache some externally provided state so that we can redraw without the + * outside telling us what to redraw, etc. + */ + +static struct pix_buf *buf_D, *buf_H; +static struct pix_buf *(*over_D_save_and_draw)(void *user, struct coord to); +static void *over_D_user; +static struct pix_buf *(*over_H_save_and_draw)(void *user); +static void *over_H_user; +static struct coord over_pos; + + +/* ----- actions ----------------------------------------------------------- */ + + +static void draw_D(void) +{ + buf_D = over_D_save_and_draw(over_D_user, over_pos); +} + + +static void draw_H(void) +{ + buf_H = over_H_save_and_draw(over_H_user); +} + + +#define STATE(s) DPRINTF("%s", #s); state = s; break; +#define restore(x) DPRINTF(" restore(%s)", #x); restore_pix_buf(buf_##x) +#define drop(x) DPRINTF(" drop(%s)", #x); free_pix_buf(buf_##x) +#define save(x) DPRINTF(" save(%s)", #x) +#define draw(x) DPRINTF(" draw(%s)", #x); draw_##x() +#define update() DPRINTF(" update"); over_pos = pos + + +/* ----- state machine ----------------------------------------------------- */ + + +void over_enter(struct pix_buf *(*save_and_draw)(void *user), void *user) +{ + over_H_save_and_draw = save_and_draw; + over_H_user = user; + + DPRINTF("enter"); + switch (state) { + case NOTHING: + save(H); + draw(H); + STATE(HOVER); + case DRAG: + restore(D); + save(H); + draw(H); + save(D); + draw(D); + STATE(BOTH); + default: + abort(); + } +} + + +void over_leave(void) +{ + DPRINTF("leave"); + switch (state) { + case HOVER: + restore(H); + STATE(NOTHING); + case BOTH: + restore(D); + restore(H); + save(D); + draw(D); + STATE(DRAG); + default: + abort(); + } +} + + +void over_begin(struct pix_buf *(*save_and_draw)(void *user, struct coord to), + void *user, struct coord pos) +{ + over_pos = pos; + over_D_save_and_draw = save_and_draw; + over_D_user = user; + + DPRINTF("begin"); + switch (state) { + case NOTHING: + save(D); + draw(D); + STATE(DRAG); + case HOVER: + save(D); + draw(D); + STATE(BOTH); + default: + abort(); + } +} + + +void over_move(struct coord pos) +{ + over_pos = pos; + + DPRINTF("move"); + switch (state) { + case NOTHING: + break; + case HOVER: + break; + case DRAG: + restore(D); + update(); + save(D); + draw(D); + STATE(DRAG); + case BOTH: + restore(D); + update(); + save(D); + draw(D); + STATE(BOTH); + default: + abort(); + } +} + + +void over_end(void) +{ + DPRINTF("end"); + switch (state) { + case DRAG: + restore(D); + STATE(NOTHING); + case BOTH: + restore(D); + STATE(HOVER); + default: + abort(); + } +} + + +void over_reset(void) +{ + DPRINTF("reset"); + switch (state) { + case NOTHING: + break; + case HOVER: + drop(H); + STATE(NOTHING); + case DRAG: + drop(D); + STATE(NOTHING); + case BOTH: + drop(D); + drop(H); + STATE(NOTHING); + default: + abort(); + } +} diff --git a/gui_over.h b/gui_over.h new file mode 100644 index 0000000..20cb249 --- /dev/null +++ b/gui_over.h @@ -0,0 +1,79 @@ +/* + * gui_over.h - GUI, canvas overlays + * + * 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 GUI_OVER_H +#define GUI_OVER_H + +/* + * Dynamic changes around the pointer are affected by the following events: + * + * - enter: enter a circle where we're hovering + * - leave: leave a circle where we've been hovering + * - begin: begin dragging + * - move: move with or without dragging + * - end: end dragging + * - reset: we got a redraw, just drop everything + * + * We have the following states: + * + * - NOTHING: neither hovering nor dragging + * - HOVER: we're hovering but not dragging + * - DRAG: we're dragging but not hovering, e.g., when searching for a place to + * end the drag + * - BOTH: we're dragging and hovering + * + * Both drag and hover save the area being changed and restore it after a + * change. We have to make sure the save/draw/restore operations are properly + * sequenced. We call the hover area H, the drag area D. This is the state + * machine that does the sequencing: + * + * NOTHING (saved: -) + * enter -> save H, draw H, HOVER + * begin -> save D, draw D, DRAG + * move -> NOTHING + * reset -> NOTHING + * + * HOVER: (saved: H) + * leave -> restore H, NOTHING + * begin -> save D, draw D, BOTH + * move -> HOVER + * reset -> drop H, NOTHING + * + * DRAG: (saved: D) + * end -> restore D, NOTHING + * enter -> restore D, save H, draw H, save D, draw D, BOTH + * move -> restore D, update, save D, draw D, DRAG + * reset -> drop D, NOTHING + * + * BOTH: (saved: D on top of H) + * end -> restore D, HOVER + * leave -> restore D, restore H, save D, draw D, DRAG + * move -> restore D, update, save D, draw D, BOTH + * reset -> drop D, drop H, NOTHING + */ + +#include "coord.h" +#include "inst.h" + + +void over_enter(struct pix_buf *(*save_and_draw)(void *user), void *user); +void over_leave(void); + +void over_begin(struct pix_buf *(*save_and_draw)(void *user, struct coord pos), + void *user, struct coord pos); +void over_move(struct coord pos); +void over_end(void); + +void over_reset(void); + +#endif /* !GUI_OVER_H */ diff --git a/gui_style.c b/gui_style.c index 076b4f0..c8db816 100644 --- a/gui_style.c +++ b/gui_style.c @@ -74,5 +74,5 @@ void gui_setup_style(GdkDrawable *drawable) 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); + gc_frame[mode_hover] = gc_vec[mode_hover] = gc("#c00000", 2); } diff --git a/gui_tools.c b/gui_tools.c index 15f1ea5..0285c1b 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_over.h" #include "gui_canvas.h" #include "gui_status.h" #include "gui.h" @@ -43,19 +44,13 @@ #include "icons/vec.xpm" -#define DA GDK_DRAWABLE(ctx->widget->window) - - 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); - int (*end_new_raw)(struct draw_ctx *ctx, struct inst *from, - struct coord to); - int (*end_new)(struct draw_ctx *ctx, struct inst *from, - struct inst *to); + void (*click)(struct coord pos); + struct pix_buf *(*drag_new)(struct inst *from, struct coord to); + int (*end_new_raw)(struct inst *from, struct coord to); + int (*end_new)(struct inst *from, struct inst *to); }; @@ -76,7 +71,6 @@ static struct drag_state { .anchors_n = 0, }; -static struct pix_buf *pix_buf; static struct coord last_canvas_pos; @@ -116,14 +110,14 @@ static struct obj *new_obj(enum obj_type type, struct inst *base) static struct pix_buf *draw_move_line_common(struct inst *inst, - struct coord end, struct draw_ctx *ctx, struct coord pos, int i) + struct coord end, struct coord pos, int i) { struct coord from, to; struct pix_buf *buf; - from = translate(ctx, inst->base); - to = translate(ctx, end); - pos = translate(ctx, pos); + from = translate(inst->base); + to = translate(end); + pos = translate(pos); switch (i) { case 0: from = pos; @@ -141,14 +135,14 @@ static struct pix_buf *draw_move_line_common(struct inst *inst, static struct pix_buf *draw_move_rect_common(struct inst *inst, - struct coord other, struct draw_ctx *ctx, struct coord pos, int i) + struct coord other, struct coord pos, int i) { struct coord min, max; struct pix_buf *buf; - min = translate(ctx, inst->base); - max = translate(ctx, other); - pos = translate(ctx, pos); + min = translate(inst->base); + max = translate(other); + pos = translate(pos); switch (i) { case 0: min = pos; @@ -167,15 +161,27 @@ static struct pix_buf *draw_move_rect_common(struct inst *inst, } +static struct pix_buf *hover_common(GdkGC *gc, struct coord center, unit_type r) +{ + struct pix_buf *buf; + + center = translate(center); + buf = save_pix_buf(DA, + center.x-r, center.y-r, center.x+r, center.y+r, 2); + draw_circle(DA, gc, FALSE, center.x, center.y, VEC_EYE_R); + return buf; +} + + /* ----- delete ------------------------------------------------------------ */ -static void click_delete(struct draw_ctx *ctx, struct coord pos) +static void click_delete(struct coord pos) { inst_deselect(); - inst_select(ctx, pos); + inst_select(pos); if (selected_inst) { - tool_dehover(ctx); + tool_dehover(); inst_delete(selected_inst); } change_world(); @@ -208,8 +214,7 @@ static struct coord gridify(struct coord base, struct coord pos) } -static struct pix_buf *drag_new_vec(struct draw_ctx *ctx, - struct inst *from, struct coord to) +static struct pix_buf *drag_new_vec(struct inst *from, struct coord to) { struct coord pos; struct pix_buf *buf; @@ -220,24 +225,29 @@ static struct pix_buf *drag_new_vec(struct draw_ctx *ctx, status_set_type_y("dX ="); status_set_x("%lg mm", units_to_mm(to.x-pos.x)); status_set_y("%lg mm", units_to_mm(to.y-pos.y)); - pos = translate(ctx, pos); - to = translate(ctx, to); + pos = translate(pos); + to = translate(to); buf = save_pix_buf(DA, pos.x, pos.y, to.x, to.y, 1); gdk_draw_line(DA, gc_drag, pos.x, pos.y, to.x, to.y); return buf; } -struct pix_buf *draw_move_vec(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_vec(struct inst *inst, struct coord pos, int i) { return draw_move_line_common(inst, - add_vec(sub_vec(inst->u.rect.end, inst->base), pos), ctx, pos, i); + add_vec(sub_vec(inst->u.rect.end, inst->base), pos), pos, i); } -static int end_new_raw_vec(struct draw_ctx *ctx, - struct inst *from, struct coord to) +struct pix_buf *gui_hover_vec(struct inst *self) +{ + return hover_common(gc_vec[mode_hover], + self->u.rect.end, VEC_EYE_R); +} + + +static int end_new_raw_vec(struct inst *from, struct coord to) { struct vec *vec; struct coord pos; @@ -260,29 +270,26 @@ static struct tool_ops vec_ops = { /* ----- line -------------------------------------------------------------- */ -static struct pix_buf *drag_new_line(struct draw_ctx *ctx, - struct inst *from, struct coord to) +static struct pix_buf *drag_new_line(struct inst *from, struct coord to) { struct coord pos; struct pix_buf *buf; - pos = translate(ctx, inst_get_point(from)); - to = translate(ctx, to); + pos = translate(inst_get_point(from)); + to = translate(to); buf = save_pix_buf(DA, pos.x, pos.y, to.x, to.y, 1); gdk_draw_line(DA, gc_drag, pos.x, pos.y, to.x, to.y); return buf; } -struct pix_buf *draw_move_line(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_line(struct inst *inst, struct coord pos, int i) { - return draw_move_line_common(inst, inst->u.rect.end, ctx, pos, i); + return draw_move_line_common(inst, inst->u.rect.end, pos, i); } -static int end_new_line(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +static int end_new_line(struct inst *from, struct inst *to) { struct obj *obj; @@ -304,14 +311,13 @@ static struct tool_ops line_ops = { /* ----- rect -------------------------------------------------------------- */ -static struct pix_buf *drag_new_rect(struct draw_ctx *ctx, - struct inst *from, struct coord to) +static struct pix_buf *drag_new_rect(struct inst *from, struct coord to) { struct coord pos; struct pix_buf *buf; - pos = translate(ctx, inst_get_point(from)); - to = translate(ctx, to); + pos = translate(inst_get_point(from)); + to = translate(to); sort_coord(&pos, &to); buf = save_pix_buf(DA, pos.x, pos.y, to.x, to.y, 1); gdk_draw_rectangle(DA, gc_drag, FALSE, @@ -320,15 +326,13 @@ static struct pix_buf *drag_new_rect(struct draw_ctx *ctx, } -struct pix_buf *draw_move_rect(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_rect(struct inst *inst, struct coord pos, int i) { - return draw_move_rect_common(inst, inst->u.rect.end, ctx, pos, i); + return draw_move_rect_common(inst, inst->u.rect.end, pos, i); } -static int end_new_rect(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +static int end_new_rect(struct inst *from, struct inst *to) { struct obj *obj; @@ -350,8 +354,7 @@ static struct tool_ops rect_ops = { /* ----- pad --------------------------------------------------------------- */ -static int end_new_pad(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +static int end_new_pad(struct inst *from, struct inst *to) { struct obj *obj; @@ -364,10 +367,9 @@ static int end_new_pad(struct draw_ctx *ctx, } -struct pix_buf *draw_move_pad(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_pad(struct inst *inst, struct coord pos, int i) { - return draw_move_rect_common(inst, inst->u.pad.other, ctx, pos, i); + return draw_move_rect_common(inst, inst->u.pad.other, pos, i); } @@ -380,15 +382,14 @@ static struct tool_ops pad_ops = { /* ----- circ -------------------------------------------------------------- */ -static struct pix_buf *drag_new_circ(struct draw_ctx *ctx, - struct inst *from, struct coord to) +static struct pix_buf *drag_new_circ(struct inst *from, struct coord to) { struct coord pos; struct pix_buf *buf; double r; - pos = translate(ctx, inst_get_point(from)); - to = translate(ctx, to); + pos = translate(inst_get_point(from)); + to = translate(to); r = hypot(to.x-pos.x, to.y-pos.y); buf = save_pix_buf(DA, pos.x-r, pos.y-r, pos.x+r, pos.y+r, 1); draw_circle(DA, gc_drag, FALSE, pos.x, pos.y, r); @@ -396,8 +397,7 @@ static struct pix_buf *drag_new_circ(struct draw_ctx *ctx, } -static int end_new_circ(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +static int end_new_circ(struct inst *from, struct inst *to) { struct obj *obj; @@ -411,19 +411,18 @@ static int end_new_circ(struct draw_ctx *ctx, } -struct pix_buf *draw_move_arc(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_arc(struct inst *inst, struct coord pos, int i) { struct coord c, from, to, end; double r, r_save, a1, a2; struct pix_buf *buf; - c = translate(ctx, inst->base); + c = translate(inst->base); from = - translate(ctx, rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a1)); + translate(rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a1)); to = - translate(ctx, rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a2)); - pos = translate(ctx, pos); + translate(rotate_r(inst->base, inst->u.arc.r, inst->u.arc.a2)); + pos = translate(pos); switch (i) { case 0: c = pos; @@ -500,15 +499,13 @@ static struct tool_ops circ_ops = { /* ----- meas -------------------------------------------------------------- */ -struct pix_buf *draw_move_meas(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i) { - return draw_move_line_common(inst, inst->u.meas.end, ctx, pos, i); + return draw_move_line_common(inst, inst->u.meas.end, pos, i); } -static int end_new_meas(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +static int end_new_meas(struct inst *from, struct inst *to) { struct obj *obj; @@ -533,9 +530,9 @@ static int meas_x_pick_vec(struct inst *inst, void *ctx) } -static void highlight_vecs(struct draw_ctx *ctx) +static void highlight_vecs(void) { - inst_highlight_vecs(ctx, meas_x_pick_vec, NULL); + inst_highlight_vecs(meas_x_pick_vec, NULL); } @@ -645,21 +642,26 @@ static void tool_selected_frame(void) /* ----- frame ------------------------------------------------------------- */ -struct pix_buf *draw_move_frame(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *draw_move_frame(struct inst *inst, struct coord pos, int i) { struct pix_buf *buf; int r = FRAME_EYE_R2; - pos = translate(ctx, pos); + pos = translate(pos); buf = save_pix_buf(DA, pos.x-r, pos.y-r, pos.x+r, pos.y+r, 1); draw_arc(DA, gc_drag, FALSE, pos.x, pos.y, r, 0, 360); return buf; } -static int end_new_frame(struct draw_ctx *ctx, - struct inst *from, struct inst *to) +struct pix_buf *gui_hover_frame(struct inst *self) +{ + return hover_common(gc_frame[mode_hover], + self->base, FRAME_EYE_R2); +} + + +static int end_new_frame(struct inst *from, struct inst *to) { struct obj *obj; @@ -745,19 +747,28 @@ static void do_move_to(struct drag_state *state, struct inst *curr) /* ----- hover ------------------------------------------------------------- */ -void tool_dehover(struct draw_ctx *ctx) +static struct pix_buf *hover_save_and_draw(void *user) { - if (hover_inst) - inst_hover(hover_inst, ctx, 0); + return inst_hover(hover_inst); +} + + +void tool_dehover(void) +{ + if (!hover_inst) + return; + over_leave(); hover_inst = NULL; } -void tool_hover(struct draw_ctx *ctx, struct coord pos) +void tool_hover(struct coord pos) { struct inst *curr; - curr = inst_find_point(ctx, pos); + curr = inst_find_point(pos); + if ((drag.new && curr == drag.new) || (drag.inst && curr == drag.inst)) + return; if (curr && !active_ops) { if (drag.anchors_n) { if (!may_move_to(&drag, curr)) @@ -768,42 +779,58 @@ void tool_hover(struct draw_ctx *ctx, struct coord pos) drag.anchors_n = 0; } } - if (curr != hover_inst) - tool_dehover(ctx); - if (curr) { - inst_hover(curr, ctx, 1); - hover_inst = curr; + if (curr == hover_inst) + return; + if (hover_inst) { + over_leave(); + hover_inst = NULL; } + if (!curr) + return; + hover_inst = curr; + over_enter(hover_save_and_draw, NULL); } /* ----- mouse actions ----------------------------------------------------- */ -int tool_consider_drag(struct draw_ctx *ctx, struct coord pos) +static struct pix_buf *drag_save_and_draw(void *user, struct coord to) +{ + if (drag.new) { + assert(active_ops); + return active_ops->drag_new(drag.new, to); + } else { + return inst_draw_move(drag.inst, to, drag.anchor_i); + } +} + + +int tool_consider_drag(struct coord pos) { struct inst *curr; assert(!drag.new); assert(!drag.anchors_n); - last_canvas_pos = translate(ctx, pos); + last_canvas_pos = translate(pos); if (active_ops && active_ops->click) { - active_ops->click(ctx, pos); + active_ops->click(pos); return 0; } - curr = inst_find_point(ctx, pos); + curr = inst_find_point(pos); if (!curr) return 0; - pix_buf = NULL; + tool_dehover(); if (active_ops) { if (active_ops->drag_new) { drag.inst = NULL; drag.new = curr; + over_begin(drag_save_and_draw, NULL, pos); return 1; } else { /* object is created without dragging */ - if (active_ops->end_new(ctx, curr, NULL)) { - tool_cancel_drag(ctx); + if (active_ops->end_new(curr, NULL)) { + tool_cancel_drag(); return -1; } return 0; @@ -813,49 +840,43 @@ int tool_consider_drag(struct draw_ctx *ctx, struct coord pos) return 0; drag.inst = selected_inst; drag.new = NULL; + over_begin(drag_save_and_draw, NULL, pos); return 1; } -void tool_drag(struct draw_ctx *ctx, struct coord to) +void tool_drag(struct coord to) { - if (pix_buf) - restore_pix_buf(pix_buf); - last_canvas_pos = translate(ctx, to); - tool_hover(ctx, to); - pix_buf = drag.new ? active_ops->drag_new(ctx, drag.new, to) : - inst_draw_move(drag.inst, ctx, to, drag.anchor_i); + last_canvas_pos = translate(to); + over_move(to); } -void tool_cancel_drag(struct draw_ctx *ctx) +void tool_cancel_drag(void) { - tool_dehover(ctx); + over_end(); + tool_dehover(); tool_reset(); - if (pix_buf) { - restore_pix_buf(pix_buf); - pix_buf = NULL; - } drag.new = NULL; active_ops = NULL; drag.anchors_n = 0; } -int tool_end_drag(struct draw_ctx *ctx, struct coord to) +int tool_end_drag(struct coord to) { struct drag_state state = drag; struct inst *end; struct tool_ops *ops = active_ops; - tool_cancel_drag(ctx); + tool_cancel_drag(); if (state.new && ops->end_new_raw) - return ops->end_new_raw(ctx, state.new, to); - end = inst_find_point(ctx, to); + return ops->end_new_raw(state.new, to); + end = inst_find_point(to); if (!end) return 0; if (state.new) - return ops->end_new(ctx, state.new, end); + return ops->end_new(state.new, end); if (!may_move_to(&state, end)) return 0; if (!inst_do_move_to(drag.inst, inst_get_vec(end), state.anchor_i)) @@ -864,15 +885,14 @@ int tool_end_drag(struct draw_ctx *ctx, struct coord to) } -void tool_redraw(struct draw_ctx *ctx) +void tool_redraw(void) { + over_reset(); if (!drag.new && !drag.anchors_n) return; - if (pix_buf) - free_pix_buf(pix_buf); - pix_buf = NULL; - tool_drag(ctx, canvas_to_coord(ctx, - last_canvas_pos.x, last_canvas_pos.y)); + tool_hover(last_canvas_pos); + over_begin(drag_save_and_draw, NULL, + canvas_to_coord(last_canvas_pos.x, last_canvas_pos.y)); } @@ -901,6 +921,7 @@ static void tool_select(GtkWidget *evbox, struct tool_ops *ops) void tool_reset(void) { + over_reset(); tool_select(ev_point, NULL); } diff --git a/gui_tools.h b/gui_tools.h index 8cf3920..b4f6ae1 100644 --- a/gui_tools.h +++ b/gui_tools.h @@ -19,30 +19,28 @@ #include "inst.h" -struct pix_buf *draw_move_vec(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_line(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_rect(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_pad(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_arc(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_meas(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); -struct pix_buf *draw_move_frame(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i); +struct pix_buf *draw_move_vec(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_line(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_rect(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_pad(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_arc(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_meas(struct inst *inst, struct coord pos, int i); +struct pix_buf *draw_move_frame(struct inst *inst, struct coord pos, int i); + +struct pix_buf *gui_hover_vec(struct inst *self); +struct pix_buf *gui_hover_frame(struct inst *self); void do_move_to_arc(struct inst *inst, struct vec *vec, int i); -void tool_dehover(struct draw_ctx *ctx); -void tool_hover(struct draw_ctx *ctx, struct coord pos); -int tool_consider_drag(struct draw_ctx *ctx, struct coord pos); -void tool_drag(struct draw_ctx *ctx, struct coord to); -void tool_cancel_drag(struct draw_ctx *ctx); -int tool_end_drag(struct draw_ctx *ctx, struct coord to); -void tool_redraw(struct draw_ctx *ctx); +void tool_dehover(void); +void tool_hover(struct coord pos); +int tool_consider_drag(struct coord pos); +void tool_drag(struct coord to); +void tool_cancel_drag(void); +int tool_end_drag(struct coord to); +void tool_redraw(void); + +struct pix_buf *tool_drag_new(struct inst *inst, struct coord pos); /* * Cache the frame and track it. diff --git a/gui_util.c b/gui_util.c index 05df08f..a5ac3aa 100644 --- a/gui_util.c +++ b/gui_util.c @@ -21,6 +21,9 @@ #include "gui_util.h" +struct draw_ctx draw_ctx; + + /* ----- look up a color --------------------------------------------------- */ diff --git a/gui_util.h b/gui_util.h index f5c6a8b..52b8390 100644 --- a/gui_util.h +++ b/gui_util.h @@ -16,6 +16,14 @@ #include +#include "coord.h" + + +struct draw_ctx { + GtkWidget *widget; + int scale; + struct coord center; +}; struct pix_buf { GdkDrawable *da; @@ -24,6 +32,12 @@ struct pix_buf { }; +extern struct draw_ctx draw_ctx; + + +#define DA GDK_DRAWABLE(draw_ctx.widget->window) + + GdkColor get_color(const char *spec); void set_width(GdkGC *gc, int width); diff --git a/inst.c b/inst.c index 82b4ba0..d90b411 100644 --- a/inst.c +++ b/inst.c @@ -20,6 +20,7 @@ #include "expr.h" #include "obj.h" #include "delete.h" +#include "gui_util.h" #include "gui_status.h" #include "gui_tools.h" #include "gui_inst.h" @@ -29,13 +30,13 @@ struct inst_ops { void (*debug)(struct inst *self); void (*save)(FILE *file, struct inst *self); - void (*draw)(struct inst *self, struct draw_ctx *ctx); - void (*hover)(struct inst *self, struct draw_ctx *ctx); + void (*draw)(struct inst *self); + struct pix_buf *(*hover)(struct inst *self); 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); - struct pix_buf *(*draw_move)(struct inst *inst, struct draw_ctx *ctx, + struct pix_buf *(*draw_move)(struct inst *inst, struct coord pos, int i); /* arcs need this special override */ void (*do_move_to)(struct inst *inst, struct vec *vec, int i); @@ -130,7 +131,7 @@ return; } -int inst_select(const struct draw_ctx *ctx, struct coord pos) +int inst_select(struct coord pos) { enum inst_prio prio; struct inst *inst; @@ -144,7 +145,7 @@ int inst_select(const struct draw_ctx *ctx, struct coord pos) for (inst = insts[prio]; inst; inst = inst->next) { if (!inst->active || !inst->ops->distance) continue; - dist = inst->ops->distance(inst, pos, ctx->scale); + dist = inst->ops->distance(inst, pos, draw_ctx.scale); if (dist >= 0 && (!selected_inst || best_dist > dist)) { selected_inst = inst; best_dist = dist; @@ -159,7 +160,7 @@ int inst_select(const struct draw_ctx *ctx, struct coord pos) for (inst = insts[ip_vec]; inst; inst = inst->next) { if (!inst->active) continue; - dist = gui_dist_vec_fallback(inst, pos, ctx->scale); + dist = gui_dist_vec_fallback(inst, pos, draw_ctx.scale); if (dist >= 0 && (!selected_inst || best_dist > dist)) { selected_inst = inst; best_dist = dist; @@ -177,7 +178,7 @@ selected: } -struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos) +struct inst *inst_find_point(struct coord pos) { struct inst *inst, *found; int best_dist = 0; /* keep gcc happy */ @@ -187,7 +188,7 @@ struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos) for (inst = insts[ip_frame]; inst; inst = inst->next) { if (!inst->u.frame.active) continue; - dist = gui_dist_frame_eye(inst, pos, ctx->scale); + dist = gui_dist_frame_eye(inst, pos, draw_ctx.scale); if (dist >= 0 && (!found || best_dist > dist)) { found = inst; best_dist = dist; @@ -199,7 +200,7 @@ struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos) for (inst = insts[ip_vec]; inst; inst = inst->next) { if (!inst->active || !inst->ops->distance) continue; - dist = inst->ops->distance(inst, pos, ctx->scale); + dist = inst->ops->distance(inst, pos, draw_ctx.scale); if (dist >= 0 && (!found || best_dist > dist)) { found = inst; best_dist = dist; @@ -821,41 +822,39 @@ void inst_revert(void) } -void inst_draw(struct draw_ctx *ctx) +void inst_draw(void) { enum inst_prio prio; struct inst *inst; FOR_INSTS_UP(prio, inst) if (!inst->active && inst->ops->draw) - inst->ops->draw(inst, ctx); + inst->ops->draw(inst); FOR_INSTS_UP(prio, inst) if (prio != ip_frame && inst->active && inst != selected_inst && inst->ops->draw) - inst->ops->draw(inst, ctx); + inst->ops->draw(inst); for (inst = insts[ip_frame]; inst; inst = inst->next) if (inst->active && inst != selected_inst && inst->ops->draw) - inst->ops->draw(inst, ctx); + inst->ops->draw(inst); if (selected_inst && selected_inst->ops->draw) - selected_inst->ops->draw(selected_inst, ctx); + selected_inst->ops->draw(selected_inst); } -void inst_highlight_vecs(struct draw_ctx *ctx, - int (*pick)(struct inst *inst, void *user), void *user) +void inst_highlight_vecs(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); + gui_highlight_vec(inst); } -struct pix_buf *inst_draw_move(struct inst *inst, struct draw_ctx *ctx, - struct coord pos, int i) +struct pix_buf *inst_draw_move(struct inst *inst, struct coord pos, int i) { - return inst->ops->draw_move(inst, ctx, pos, i); + return inst->ops->draw_move(inst, pos, i); } @@ -868,14 +867,11 @@ 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) +struct pix_buf *inst_hover(struct inst *inst) { if (!inst->ops->hover) - return; - if (on) - inst->ops->hover(inst, ctx); - else - inst->ops->draw(inst, ctx); + return NULL; + return inst->ops->hover(inst); } diff --git a/inst.h b/inst.h index 00f9dce..4f27381 100644 --- a/inst.h +++ b/inst.h @@ -37,7 +37,6 @@ struct bbox { }; struct inst_ops; -struct draw_ctx; struct inst { const struct inst_ops *ops; @@ -83,10 +82,10 @@ extern struct bbox active_frame_bbox; void inst_select_outside(void *item, void (*deselect)(void *item)); -int inst_select(const struct draw_ctx *ctx, struct coord pos); +int inst_select(struct coord pos); void inst_deselect(void); -struct inst *inst_find_point(const struct draw_ctx *ctx, struct coord pos); +struct inst *inst_find_point(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_vec(const struct inst *inst); @@ -113,13 +112,12 @@ void inst_start(void); 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); +void inst_draw(void); +void inst_highlight_vecs(int (*pick)(struct inst *inst, void *user), + void *user); +struct pix_buf *inst_draw_move(struct inst *inst, 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); +struct pix_buf *inst_hover(struct inst *inst); void inst_delete(struct inst *inst); void inst_debug(void);