diff --git a/Makefile b/Makefile index 856451f..d7f6f91 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,8 @@ OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \ gui_tool.o gui_over.o gui_meas.o gui_frame.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 + line.xpm rect.xpm pad.xpm circ.xpm meas.xpm meas_x.xpm meas_y.xpm \ + stuff.xpm stuff_off.xpm meas_off.xpm CFLAGS_GTK = `pkg-config --cflags gtk+-2.0` LIBS_GTK = `pkg-config --libs gtk+-2.0` @@ -95,7 +96,7 @@ y.tab.c y.tab.h: fpd.y y.tab.o: y.tab.c $(CC) -c $(CFLAGS) $(SLOPPY) y.tab.c -gui_tool.o: $(XPMS:%=icons/%) +gui_tool.o gui.o: $(XPMS:%=icons/%) # ----- Dependencies ---------------------------------------------------------- diff --git a/gui.c b/gui.c index 8e349c9..d6b91f6 100644 --- a/gui.c +++ b/gui.c @@ -24,10 +24,20 @@ #include "gui_frame.h" #include "gui.h" +#include "icons/stuff.xpm" +#include "icons/stuff_off.xpm" +#include "icons/meas.xpm" +#include "icons/meas_off.xpm" + GtkWidget *root; +int show_stuff = 1; +int show_meas = 1; + static GtkWidget *frames_box; +static GtkWidget *ev_stuff, *ev_meas; +static GtkWidget *stuff_image[2], *meas_image[2]; /* ----- menu bar ---------------------------------------------------------- */ @@ -39,13 +49,13 @@ static void menu_save(GtkWidget *widget, gpointer user) } -static void make_menu_bar(GtkWidget *vbox) +static void make_menu_bar(GtkWidget *hbox) { GtkWidget *bar; GtkWidget *file_menu, *file, *quit, *save; bar = gtk_menu_bar_new(); - gtk_box_pack_start(GTK_BOX(vbox), bar, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), bar, TRUE, TRUE, 0); file_menu = gtk_menu_new(); @@ -65,6 +75,67 @@ static void make_menu_bar(GtkWidget *vbox) } +static gboolean toggle_stuff(GtkWidget *widget, GdkEventButton *event, + gpointer data) +{ + switch (event->button) { + case 1: + show_stuff = !show_stuff; + set_image(ev_stuff, stuff_image[show_stuff]); + redraw(); + break; + } + return TRUE; +} + + +static gboolean toggle_meas(GtkWidget *widget, GdkEventButton *event, + gpointer data) +{ + switch (event->button) { + case 1: + show_meas = !show_meas; + set_image(ev_meas, meas_image[show_meas]); + redraw(); + break; + } + return TRUE; +} + + +static void make_tool_bar(GtkWidget *hbox, GdkDrawable *drawable) +{ + GtkWidget *bar; + + bar = gtk_toolbar_new(); + gtk_box_pack_end(GTK_BOX(hbox), bar, TRUE, TRUE, 0); + //gtk_box_pack_end(GTK_BOX(hbox), bar, FALSE, FALSE, 0); + gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS); + + ev_stuff = tool_button(bar, drawable, NULL, toggle_stuff, NULL); + ev_meas = tool_button(bar, drawable, NULL, toggle_meas, NULL); + + stuff_image[0] = gtk_widget_ref(make_image(drawable, xpm_stuff_off)); + stuff_image[1] = gtk_widget_ref(make_image(drawable, xpm_stuff)); + meas_image[0] = gtk_widget_ref(make_image(drawable, xpm_meas_off)); + meas_image[1] = gtk_widget_ref(make_image(drawable, xpm_meas)); + + set_image(ev_stuff, stuff_image[show_stuff]); + set_image(ev_meas, meas_image[show_meas]); +} + + +static void make_top_bar(GtkWidget *vbox) +{ + GtkWidget *hbox; + + hbox = gtk_hbox_new(FALSE, 0); + make_menu_bar(hbox); + make_tool_bar(hbox, root->window); + gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, FALSE, 0); +} + + /* ----- central screen area ----------------------------------------------- */ @@ -125,7 +196,7 @@ static void make_screen(GtkWidget *window) vbox = gtk_vbox_new(FALSE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); - make_menu_bar(vbox); + make_top_bar(vbox); make_center_area(vbox); make_status_area(vbox); } diff --git a/gui.h b/gui.h index 8be6593..a1dbae0 100644 --- a/gui.h +++ b/gui.h @@ -18,6 +18,8 @@ extern GtkWidget *root; +extern int show_stuff; +extern int show_meas; /* update everything after a model change */ diff --git a/gui_meas.c b/gui_meas.c index 928a5db..37b9bf2 100644 --- a/gui_meas.c +++ b/gui_meas.c @@ -286,8 +286,10 @@ static int end_new_meas(struct inst *from, struct inst *to) default: abort(); } - meas->inverted = meas_dsc->lt(from->u.rect.end, to->u.rect.end) != - (mode == min_to_next_or_max); + meas->inverted = + mode == min_to_next_or_max && is_min(meas_dsc->lt, to) ? 0 : + meas_dsc->lt(from->u.rect.end, to->u.rect.end) != + (mode == min_to_next_or_max); { char *sm[] = { "min_to", "max_to", "next_to" }; char *st[] = { "nxy", "nx", "ny", "mxy", "mx", "my" }; diff --git a/gui_tool.c b/gui_tool.c index 67f787d..a032065 100644 --- a/gui_tool.c +++ b/gui_tool.c @@ -510,17 +510,9 @@ static int is_parent_of(const struct frame *p, const struct frame *c) static struct frame *locked_frame = NULL; -static void remove_child(GtkWidget *widget, gpointer data) -{ - gtk_container_remove(GTK_CONTAINER(data), widget); -} - - static void set_frame_image(GtkWidget *image) { - gtk_container_foreach(GTK_CONTAINER(ev_frame), remove_child, ev_frame); - gtk_container_add(GTK_CONTAINER(ev_frame), image); - gtk_widget_show_all(ev_frame); + set_image(ev_frame, image); } @@ -851,63 +843,12 @@ void tool_reset(void) static gboolean tool_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer data) { - tool_select(widget, data); - return TRUE; -} - - -static GtkWidget *make_image(GdkDrawable *drawable, char **xpm) -{ - GdkPixmap *pixmap; - GtkWidget *image; - - pixmap = gdk_pixmap_create_from_xpm_d(drawable, NULL, NULL, xpm); - image = gtk_image_new_from_pixmap(pixmap, NULL); - gtk_misc_set_padding(GTK_MISC(image), 1, 1); - return image; -} - - -static GtkWidget *tool_button(GtkWidget *bar, GdkDrawable *drawable, - char **xpm, GtkWidget *last_evbox, struct tool_ops *ops) -{ - GtkWidget *image, *evbox; - GtkToolItem *item; - GtkToolItem *last = NULL; - - if (last_evbox) - last = GTK_TOOL_ITEM(gtk_widget_get_ancestor(last_evbox, - GTK_TYPE_TOOL_ITEM)); - -/* - * 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 - evbox = gtk_event_box_new(); - if (xpm) { - image = make_image(drawable, xpm); - gtk_container_add(GTK_CONTAINER(evbox), image); + switch (event->button) { + case 1: + tool_select(widget, data); + break; } - g_signal_connect(G_OBJECT(evbox), "button_press_event", - G_CALLBACK(tool_button_press_event), ops); - - item = gtk_tool_item_new(); - gtk_container_add(GTK_CONTAINER(item), evbox); - - gtk_container_set_border_width(GTK_CONTAINER(item), 0); -#endif - - gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1); - - return evbox; + return TRUE; } @@ -924,27 +865,36 @@ static void tool_separator(GtkWidget *bar) GtkWidget *gui_setup_tools(GdkDrawable *drawable) { GtkWidget *bar; - GtkWidget *last; bar = gtk_toolbar_new(); gtk_toolbar_set_style(GTK_TOOLBAR(bar), GTK_TOOLBAR_ICONS); gtk_toolbar_set_orientation(GTK_TOOLBAR(bar), GTK_ORIENTATION_VERTICAL); - ev_point = tool_button(bar, drawable, xpm_point, NULL, NULL); - last = tool_button(bar, drawable, xpm_delete, ev_point, &delete_ops); + ev_point = tool_button(bar, drawable, xpm_point, + tool_button_press_event, NULL); + tool_button(bar, drawable, xpm_delete, + tool_button_press_event, &delete_ops); tool_separator(bar); - last = tool_button(bar, drawable, xpm_vec, last, &vec_ops); - ev_frame = tool_button(bar, drawable, NULL, last, &frame_ops); - last = ev_frame; - last = tool_button(bar, drawable, xpm_pad, last, &pad_ops); - last = tool_button(bar, drawable, xpm_line, last, &line_ops); - last = tool_button(bar, drawable, xpm_rect, last, &rect_ops); - last = tool_button(bar, drawable, xpm_circ, last, &circ_ops); + tool_button(bar, drawable, xpm_vec, + tool_button_press_event, &vec_ops); + ev_frame = tool_button(bar, drawable, NULL, + tool_button_press_event, &frame_ops); + tool_button(bar, drawable, xpm_pad, + tool_button_press_event, &pad_ops); + tool_button(bar, drawable, xpm_line, + tool_button_press_event, &line_ops); + tool_button(bar, drawable, xpm_rect, + tool_button_press_event, &rect_ops); + tool_button(bar, drawable, xpm_circ, + tool_button_press_event, &circ_ops); tool_separator(bar); - last = tool_button(bar, drawable, xpm_meas, last, &meas_ops); - last = tool_button(bar, drawable, xpm_meas_x, last, &meas_ops_x); - last = tool_button(bar, drawable, xpm_meas_y, last, &meas_ops_y); + tool_button(bar, drawable, xpm_meas, + tool_button_press_event, &meas_ops); + tool_button(bar, drawable, xpm_meas_x, + tool_button_press_event, &meas_ops_x); + tool_button(bar, drawable, xpm_meas_y, + tool_button_press_event, &meas_ops_y); frame_image = gtk_widget_ref(make_image(drawable, xpm_frame)); frame_image_locked = diff --git a/gui_util.c b/gui_util.c index a5ac3aa..b418bea 100644 --- a/gui_util.c +++ b/gui_util.c @@ -161,6 +161,67 @@ void label_in_box_bg(GtkWidget *label, const char *color) } +/* ----- generate a tool button with an XPM image -------------------------- */ + + +GtkWidget *make_image(GdkDrawable *drawable, char **xpm) +{ + GdkPixmap *pixmap; + GtkWidget *image; + + pixmap = gdk_pixmap_create_from_xpm_d(drawable, NULL, NULL, xpm); + image = gtk_image_new_from_pixmap(pixmap, NULL); + gtk_misc_set_padding(GTK_MISC(image), 1, 1); + return image; +} + + +static void remove_child(GtkWidget *widget, gpointer data) +{ + gtk_container_remove(GTK_CONTAINER(data), widget); +} + + +void set_image(GtkWidget *widget, GtkWidget *image) +{ + gtk_container_foreach(GTK_CONTAINER(widget), remove_child, widget); + gtk_container_add(GTK_CONTAINER(widget), image); + gtk_widget_show_all(widget); +} + + +GtkWidget *tool_button(GtkWidget *bar, GdkDrawable *drawable, char **xpm, + gboolean (*cb)(GtkWidget *widget, GdkEventButton *event, gpointer data), + gpointer data) +{ + GtkWidget *image, *evbox; + GtkToolItem *item; + + /* + * gtk_radio_tool_button_new_from_widget is *huge*. We try to do things + * in a + * more compact way. + */ + + evbox = gtk_event_box_new(); + if (xpm) { + image = make_image(drawable, xpm); + gtk_container_add(GTK_CONTAINER(evbox), image); + } + g_signal_connect(G_OBJECT(evbox), "button_press_event", + G_CALLBACK(cb), data); + + item = gtk_tool_item_new(); + gtk_container_add(GTK_CONTAINER(item), evbox); + + gtk_container_set_border_width(GTK_CONTAINER(item), 0); + + gtk_toolbar_insert(GTK_TOOLBAR(bar), item, -1); + + return evbox; +} + + /* ----- render a text string ---------------------------------------------- */ diff --git a/gui_util.h b/gui_util.h index 52b8390..5bd2090 100644 --- a/gui_util.h +++ b/gui_util.h @@ -56,6 +56,12 @@ GtkWidget *label_in_box_new(const char *s); GtkWidget *box_of_label(GtkWidget *label); void label_in_box_bg(GtkWidget *box, const char *color); +GtkWidget *make_image(GdkDrawable *drawable, char **xpm); +void set_image(GtkWidget *widget, GtkWidget *image); +GtkWidget *tool_button(GtkWidget *bar, GdkDrawable *drawable, char **xpm, + gboolean (*cb)(GtkWidget *widget, GdkEventButton *event, gpointer data), + gpointer data); + void render_text(GdkDrawable *da, GdkGC *gc, int x, int y, double angle, const char *s, const char *font, double xalign, double yalign, int xmax, int ymax); diff --git a/icons/meas_off.fig b/icons/meas_off.fig new file mode 100644 index 0000000..97e03cb --- /dev/null +++ b/icons/meas_off.fig @@ -0,0 +1,19 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +2 2 0 1 0 7 50 -1 10 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 +2 1 0 10 0 7 40 -1 -1 0.000 0 0 -1 0 0 2 + 3900 3600 4200 4200 +2 1 0 10 0 7 40 -1 -1 0.000 0 0 -1 1 1 2 + 0 0 10.00 450.00 450.00 + 0 0 10.00 450.00 450.00 + 4050 3900 5550 3150 +2 1 0 10 0 7 40 -1 -1 0.000 0 0 -1 0 0 2 + 5400 2850 5700 3450 diff --git a/icons/stuff.fig b/icons/stuff.fig new file mode 100644 index 0000000..08f2d82 --- /dev/null +++ b/icons/stuff.fig @@ -0,0 +1,17 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +0 32 #c0c000 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 +2 1 0 10 32 7 50 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 10.00 300.00 300.00 + 3900 4515 5700 3315 +2 1 0 10 12 7 50 -1 -1 0.000 0 1 -1 0 0 3 + 3900 3600 3900 2760 5700 2760 diff --git a/icons/stuff_off.fig b/icons/stuff_off.fig new file mode 100644 index 0000000..b921711 --- /dev/null +++ b/icons/stuff_off.fig @@ -0,0 +1,17 @@ +#FIG 3.2 Produced by xfig version 3.2.5a +Landscape +Center +Inches +A4 +100.00 +Single +-2 +1200 2 +0 32 #c0c000 +2 1 0 10 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 10.00 300.00 300.00 + 3900 4515 5700 3315 +2 1 0 10 0 7 40 -1 -1 0.000 0 1 -1 0 0 3 + 3900 3600 3900 2760 5700 2760 +2 2 0 1 0 7 50 -1 10 0.000 0 0 -1 0 0 5 + 3600 2400 6000 2400 6000 4800 3600 4800 3600 2400 diff --git a/inst.c b/inst.c index 28d1d33..159fe5e 100644 --- a/inst.c +++ b/inst.c @@ -24,6 +24,7 @@ #include "gui_status.h" #include "gui_tool.h" #include "gui_inst.h" +#include "gui.h" #include "inst.h" @@ -83,6 +84,23 @@ static unsigned long active_set = 0; #define IS_ACTIVE ((active_set & 1)) +/* ----- selective visibility ---------------------------------------------- */ + + +static int show(enum inst_prio prio) +{ + switch (prio) { + case ip_vec: + case ip_frame: + return show_stuff; + case ip_meas: + return show_meas; + default: + return 1; + } +} + + /* ----- selection of items not on the canvas ------------------------------ */ @@ -142,6 +160,8 @@ int inst_select(struct coord pos) edit_nothing(); selected_inst = NULL; FOR_INST_PRIOS_DOWN(prio) { + if (!show(prio)) + continue; for (inst = insts[prio]; inst; inst = inst->next) { if (!inst->active || !inst->ops->distance) continue; @@ -155,6 +175,9 @@ int inst_select(struct coord pos) goto selected; } + if (!show_stuff) + return 0; + /* give vectors a second chance */ for (inst = insts[ip_vec]; inst; inst = inst->next) { @@ -828,15 +851,17 @@ void inst_draw(void) struct inst *inst; FOR_INSTS_UP(prio, inst) - if (!inst->active && inst->ops->draw) + if (show(prio) && !inst->active && inst->ops->draw) inst->ops->draw(inst); FOR_INSTS_UP(prio, inst) - if (prio != ip_frame && inst->active && + if (show(prio) && prio != ip_frame && inst->active && inst != selected_inst && inst->ops->draw) 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); + if (show_stuff) + for (inst = insts[ip_frame]; inst; inst = inst->next) + if (inst->active && inst != selected_inst && + inst->ops->draw) + inst->ops->draw(inst); if (selected_inst && selected_inst->ops->draw) selected_inst->ops->draw(selected_inst); }