From 4bfb601a40bf205cef041eaaeee38cc56dc01896 Mon Sep 17 00:00:00 2001 From: werner Date: Fri, 19 Feb 2010 10:27:46 +0000 Subject: [PATCH] Wrap wide tables. - gui_frame.c (build_table): restructured code to build tables column by column instead of row by row - gui_frame.c (build_table): wrap tables wider than the screen area available for variables and tables - gui_util.h, gui_util.c (get_widget_width): new helper function that returns a widget's requested width - gui.c, gui_style.h: replace hard-coded initial pane size with constants DEFAULT_FRAME_AREA_WIDTH and DEFAULT_FRAME_AREA_HEIGHT - gui.c (change_world): pass the width of the left pane as a wrapping hint to build_frames - gui_frame.c (build_frames): subtract width of longest package template or frame name from available width - gui.c (change_world): moved call to build_frames to separate function do_build_frames - gui.c (gui_main): used g_signal_connect_swapped instead of g_signal_connect for no good reason git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5847 99fdad57-331a-0410-800a-d7fa5415bdb3 --- gui.c | 38 ++++++++++++++--- gui_frame.c | 120 ++++++++++++++++++++++++++++++++++++++-------------- gui_frame.h | 6 +-- gui_style.h | 8 +++- gui_util.c | 13 ++++++ gui_util.h | 2 + 6 files changed, 145 insertions(+), 42 deletions(-) diff --git a/gui.c b/gui.c index 1665c54..9d32643 100644 --- a/gui.c +++ b/gui.c @@ -41,11 +41,14 @@ int show_meas = 1; int show_bright = 0; +static GtkWidget *paned; static GtkWidget *frames_box; static GtkWidget *ev_stuff, *ev_meas, *ev_all, *ev_bright; static GtkWidget *stuff_image[2], *meas_image[2], *all_image[2]; static GtkWidget *bright_image[2]; +static void do_build_frames(void); + /* ----- view callbacks ---------------------------------------------------- */ @@ -220,9 +223,21 @@ static void make_top_bar(GtkWidget *vbox) /* ----- central screen area ----------------------------------------------- */ +static void resize_frames_area(GtkWidget *widget, GtkAllocation *allocation, + gpointer user_data) +{ + static int width = 0; + + if (allocation->width == width) + return; + width = allocation->width; + do_build_frames(); +} + + static void make_center_area(GtkWidget *vbox) { - GtkWidget *hbox, *frames_area, *paned; + GtkWidget *hbox, *frames_area;//, *paned; GtkWidget *tools; hbox = gtk_hbox_new(FALSE, 0); @@ -237,14 +252,18 @@ static void make_center_area(GtkWidget *vbox) gtk_paned_add1(GTK_PANED(paned), frames_area); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(frames_area), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - gtk_widget_set_size_request(frames_area, 250, 100); + gtk_widget_set_size_request(frames_area, + DEFAULT_FRAME_AREA_WIDTH, DEFAULT_FRAME_AREA_HEIGHT); frames_box = gtk_vbox_new(FALSE, 0); - build_frames(frames_box); + build_frames(frames_box, DEFAULT_FRAME_AREA_WIDTH); gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(frames_area), frames_box); + g_signal_connect(G_OBJECT(frames_area), "size-allocate", + G_CALLBACK(resize_frames_area), NULL); + /* Canvas */ gtk_paned_add2(GTK_PANED(paned), make_canvas()); @@ -259,6 +278,15 @@ static void make_center_area(GtkWidget *vbox) /* ----- GUI construction -------------------------------------------------- */ +static void do_build_frames(void) +{ + int width; + + width = gtk_paned_get_position(GTK_PANED(paned)); + build_frames(frames_box, width > 0 ? width : DEFAULT_FRAME_AREA_WIDTH); +} + + void change_world(void) { struct bbox before, after; @@ -269,7 +297,7 @@ void change_world(void) instantiate(); after = inst_get_bbox(); label_in_box_bg(active_frame->label, COLOR_FRAME_SELECTED); - build_frames(frames_box); + do_build_frames(); if (after.min.x < before.min.x || after.min.y < before.min.y || after.max.x > before.max.x || after.max.y > before.max.y) zoom_to_extents(); @@ -323,7 +351,7 @@ int gui_main(void) /* get root->window */ gtk_widget_show_all(root); - g_signal_connect_swapped(G_OBJECT(root), "destroy", + g_signal_connect(G_OBJECT(root), "destroy", G_CALLBACK(gtk_main_quit), NULL); make_screen(root); diff --git a/gui_frame.c b/gui_frame.c index f30f828..2e30976 100644 --- a/gui_frame.c +++ b/gui_frame.c @@ -955,8 +955,10 @@ static gboolean table_scroll_event(GtkWidget *widget, GdkEventScroll *event, } +/* @@@ this function is too long */ + static void build_table(GtkWidget *vbox, struct frame *frame, - struct table *table) + struct table *table, int wrap_width) { GtkWidget *tab, *field; GtkWidget *evbox, *align; @@ -964,8 +966,9 @@ static void build_table(GtkWidget *vbox, struct frame *frame, struct row *row; struct value *value; int n_vars = 0, n_rows = 0; + int n_var, n_row, pos, col; char *expr; - GdkColor col; + GdkColor color; for (var = table->vars; var; var = var->next) n_vars++; @@ -975,26 +978,40 @@ static void build_table(GtkWidget *vbox, struct frame *frame, if (n_vars == 1 && n_rows == 1) return; - evbox = gtk_event_box_new(); - align = gtk_alignment_new(0, 0, 0, 0); - gtk_container_add(GTK_CONTAINER(align), evbox); - gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, FALSE, 0); - - tab = gtk_table_new(n_rows+1, n_vars, FALSE); - gtk_container_add(GTK_CONTAINER(evbox), tab); - col = get_color(COLOR_VAR_TABLE_SEP); - gtk_widget_modify_bg(GTK_WIDGET(evbox), - GTK_STATE_NORMAL, &col); - - gtk_table_set_row_spacings(GTK_TABLE(tab), 1); - gtk_table_set_col_spacings(GTK_TABLE(tab), 1); - + var = table->vars; + n_var = 0; n_vars = 0; - for (var = table->vars; var; var = var->next) { + while (var) { + col = n_vars+(n_var != n_vars);; + if (!n_vars) { + evbox = gtk_event_box_new(); + align = gtk_alignment_new(0, 0, 0, 0); + gtk_container_add(GTK_CONTAINER(align), evbox); + gtk_box_pack_start(GTK_BOX(vbox), align, + FALSE, FALSE, 0); + + tab = gtk_table_new(n_rows+1, col, FALSE); + gtk_container_add(GTK_CONTAINER(evbox), tab); + color = get_color(COLOR_VAR_TABLE_SEP); + gtk_widget_modify_bg(GTK_WIDGET(evbox), + GTK_STATE_NORMAL, &color); + + gtk_table_set_row_spacings(GTK_TABLE(tab), 1); + gtk_table_set_col_spacings(GTK_TABLE(tab), 1); + + /* @@@ + * for now, we just add an empty first column to + * wrapped tables, which yields a thin black line. + * Might want to put something more visible later. + */ + + } + gtk_table_resize(GTK_TABLE(tab), n_rows, col+1); + field = label_in_box_new(var->name, "Variable (column) name. Click to edit."); gtk_table_attach_defaults(GTK_TABLE(tab), box_of_label(field), - n_vars, n_vars+1, 0, 1); + col, col+1, 0, 1); label_in_box_bg(field, COLOR_VAR_PASSIVE); g_signal_connect(G_OBJECT(box_of_label(field)), "button_press_event", @@ -1003,20 +1020,20 @@ static void build_table(GtkWidget *vbox, struct frame *frame, "scroll_event", G_CALLBACK(table_scroll_event), table); var->widget = field; - n_vars++; - } - n_rows = 0; - for (row = table->rows; row; row = row->next) { - n_vars = 0; - for (value = row->values; value; value = value->next) { + + n_row = 0; + for (row = table->rows; row; row = row->next) { + value = row->values; + for (pos = 0; pos != n_var; pos++) + value = value->next; expr = unparse(value->expr); field = label_in_box_new(expr, "Variable value. Click to select row or to edit."); free(expr); gtk_table_attach_defaults(GTK_TABLE(tab), box_of_label(field), - n_vars, n_vars+1, - n_rows+1, n_rows+2); + col, col+1, + n_row+1, n_row+2); label_in_box_bg(field, table->active_row == row ? COLOR_ROW_SELECTED : COLOR_ROW_UNSELECTED); g_signal_connect(G_OBJECT(box_of_label(field)), @@ -1026,10 +1043,39 @@ static void build_table(GtkWidget *vbox, struct frame *frame, "scroll_event", G_CALLBACK(table_scroll_event), table); value->widget = field; - n_vars++; + n_row++; } - n_rows++; + + /* + * Wrap tables wider than the screen area available for + * variables and tables. Don't wrap before having output at + * least one column. + */ + if (n_vars && get_widget_width(tab) > wrap_width) { + /* + * Resizing alone doesn't hide extra columns. We have + * to explicitly remove their content as well. + */ + gtk_container_remove(GTK_CONTAINER(tab), + box_of_label(var->widget)); + for (row = table->rows; row; row = row->next) { + value = row->values; + for (pos = 0; pos != n_var; pos++) + value = value->next; + gtk_container_remove(GTK_CONTAINER(tab), + box_of_label(value->widget)); + } + gtk_table_resize(GTK_TABLE(tab), n_rows, col); + + n_vars = 0; + continue; + } + + var = var->next; + n_var++; + n_vars++; } + } @@ -1220,7 +1266,7 @@ static void build_loop(GtkWidget *vbox, struct frame *frame, /* ----- the list of variables, tables, and loops -------------------------- */ -static GtkWidget *build_vars(struct frame *frame) +static GtkWidget *build_vars(struct frame *frame, int wrap_width) { GtkWidget *vbox; struct table *table; @@ -1230,7 +1276,7 @@ static GtkWidget *build_vars(struct frame *frame) for (table = frame->tables; table; table = table->next) { add_sep(vbox, 3); build_assignment(vbox, frame, table); - build_table(vbox, frame, table); + build_table(vbox, frame, table, wrap_width); } for (loop = frame->loops; loop; loop = loop->next) { add_sep(vbox, 3); @@ -1696,11 +1742,12 @@ static GtkWidget *build_frame_refs(const struct frame *frame) /* ----- frames ------------------------------------------------------------ */ -void build_frames(GtkWidget *vbox) +void build_frames(GtkWidget *vbox, int wrap_width) { struct frame *frame; GtkWidget *hbox, *tab, *label, *packages, *refs, *vars, *items, *meas; int n = 0; + int max_name_width, name_width; destroy_all_children(GTK_CONTAINER(vbox)); for (frame = frames; frame; frame = frame->next) @@ -1717,6 +1764,7 @@ void build_frames(GtkWidget *vbox) label = build_pkg_name(); gtk_table_attach_defaults(GTK_TABLE(tab), label, 0, 1, 0, 1); + max_name_width = get_widget_width(label); packages = build_pkg_names(); gtk_table_attach_defaults(GTK_TABLE(tab), packages, 1, 2, 0, 1); @@ -1726,13 +1774,21 @@ void build_frames(GtkWidget *vbox) label = build_frame_label(frame); gtk_table_attach_defaults(GTK_TABLE(tab), label, 0, 1, n*2+1, n*2+2); + n++; + name_width = get_widget_width(label); + if (name_width > max_name_width) + max_name_width = name_width; + } + wrap_width -= max_name_width+FRAME_AREA_MISC_WIDTH; + n = 0; + for (frame = root_frame; frame; frame = frame->prev) { refs = build_frame_refs(frame); gtk_table_attach_defaults(GTK_TABLE(tab), refs, 1, 2, n*2+1, n*2+2); if (show_vars) { - vars = build_vars(frame); + vars = build_vars(frame, wrap_width); gtk_table_attach_defaults(GTK_TABLE(tab), vars, 1, 2, n*2+2, n*2+3); dont_build_items(frame); diff --git a/gui_frame.h b/gui_frame.h index 1c8da9f..2922605 100644 --- a/gui_frame.h +++ b/gui_frame.h @@ -1,8 +1,8 @@ /* * gui_frame.h - GUI, frame window * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 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 @@ -27,6 +27,6 @@ void select_frame(struct frame *frame); void gui_frame_select_inst(struct inst *inst); void gui_frame_deselect_inst(struct inst *inst); -void build_frames(GtkWidget *vbox); +void build_frames(GtkWidget *vbox, int warp_width); #endif /* !GUI_FRAME_H */ diff --git a/gui_style.h b/gui_style.h index 9481dcf..f3468e3 100644 --- a/gui_style.h +++ b/gui_style.h @@ -1,8 +1,8 @@ /* * gui_style.h - GUI, style definitions * - * Written 2009 by Werner Almesberger - * Copyright 2009 by Werner Almesberger + * Written 2009, 2010 by Werner Almesberger + * Copyright 2009, 2010 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 @@ -61,6 +61,10 @@ #define MM_FORMAT_SHORT "%.4g" #define MIL_FORMAT_SHORT "%.4g" +#define DEFAULT_FRAME_AREA_WIDTH 250 +#define DEFAULT_FRAME_AREA_HEIGHT 100 +#define FRAME_AREA_MISC_WIDTH 26 /* pane, scroll bar, slack */ + /* ----- assorted colors --------------------------------------------------- */ diff --git a/gui_util.c b/gui_util.c index aeca743..c3adeb6 100644 --- a/gui_util.c +++ b/gui_util.c @@ -387,3 +387,16 @@ void destroy_all_children(GtkContainer *container) { gtk_container_foreach(container, destroy_callback, NULL); } + + +/* ----- get a widget's desired width -------------------------------------- */ + + +int get_widget_width(GtkWidget *widget) +{ + GtkRequisition req; + + gtk_widget_show_all(widget); + gtk_widget_size_request(widget, &req); + return req.width; +} diff --git a/gui_util.h b/gui_util.h index 240cf83..20e074a 100644 --- a/gui_util.h +++ b/gui_util.h @@ -79,4 +79,6 @@ void debug_save_widget(GtkWidget *widget); void destroy_all_children(GtkContainer *container); +int get_widget_width(GtkWidget *widget); + #endif /* !GUI_UTIL_H */