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
This commit is contained in:
werner 2010-02-19 10:27:46 +00:00
parent 3ba5a476b8
commit 4bfb601a40
6 changed files with 145 additions and 42 deletions

38
gui.c
View File

@ -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);

View File

@ -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);

View File

@ -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 */

View File

@ -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 --------------------------------------------------- */

View File

@ -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;
}

View File

@ -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 */