From c3db07b4ec29ce9e69681849566c1c90609d0360 Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Fri, 19 Oct 2012 17:15:58 +0200 Subject: [PATCH] Use different tables for different dialog columns Making the same table wider (in steps of 3) to get multiple columns does not work, because it forces options to align vertically. This wrecks dialogs like Load Engine, where one column contains a very high option (listbox). Now differnt tables are created for each column, packed in a new itermediate hbox. In case of the Engine Output window, a vbox is used instead to cause vertical stacking. Only multi-line text-edits and listboxes are now allowed to take up vertical space changes, while only the middle colum of the table can take up horizontal size changes. Within packing boxes space is equally distributed. The labels above the particiant-selection widgets had not the same width as the textview / listbox, leading to misplacement of the second label. For Engine Settings the spontaneous breaking into columns did not involve a SAME_ROW flag, so the 'columns' were stacked vertically. In addition the columns were too tall for GTK. They are now 20 options max. --- dialogs.c | 4 +- xoptions.c | 89 ++++++++++++++++++++++++++++++++++++++--------------------- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/dialogs.c b/dialogs.c index 22577e7..32f1e34 100644 --- a/dialogs.c +++ b/dialogs.c @@ -261,8 +261,8 @@ static Option matchOptions[] = { { 0, SAME_ROW|LL, 0, NULL, NULL, "", NULL, Label, N_(" (for concurrent playing of a single") }, { 0, 0, 0, NULL, (void*) &appData.cycleSync, "", NULL, CheckBox, N_("Sync after cycle") }, { 0, SAME_ROW|LL, 0, NULL, NULL, "", NULL, Label, N_(" tourney with multiple XBoards)") }, -{ 0, LR, 200, NULL, NULL, "", NULL, Label, N_("Tourney participants:") }, -{ 0, SAME_ROW|RR, 0, NULL, NULL, "", NULL, Label, N_("Select Engine:") }, +{ 0, LR, 175, NULL, NULL, "", NULL, Label, N_("Tourney participants:") }, +{ 0, SAME_ROW|RR, 175, NULL, NULL, "", NULL, Label, N_("Select Engine:") }, { 150, T_VSCRL | T_FILL | T_WRAP, 175, NULL, (void*) &engineName, "", NULL, TextBox, "" }, { 150, SAME_ROW|RR, diff --git a/xoptions.c b/xoptions.c index 583ab9d..b823553 100644 --- a/xoptions.c +++ b/xoptions.c @@ -1052,16 +1052,25 @@ SetPositionAndSize (Arg *args, Widget leftNeigbor, Widget topNeigbor, int b, int #endif static int +TableWidth (Option *opt) +{ // Hideous work-around! If the table is 3 columns, but 2 & 3 are always occupied together, the fixing of the width of column 1 does not work + while(opt->type != EndMark && opt->type != Break) + if(opt->type == FileName || opt++->type == PathName) return 3; // This table needs browse button + return 2; // no browse button; +} + +static int SameRow (Option *opt) { return (opt->min & SAME_ROW && (opt->type == Button || opt->type == SaveButton || opt->type == Label || opt->type == ListBox)); } static void -Pack (GtkWidget *hbox, GtkWidget *table, GtkWidget *entry, int left, int right, int top) +Pack (GtkWidget *hbox, GtkWidget *table, GtkWidget *entry, int left, int right, int top, GtkAttachOptions vExpand) { if(hbox) gtk_box_pack_start(GTK_BOX (hbox), entry, TRUE, TRUE, 0); - else gtk_table_attach_defaults(GTK_TABLE(table), entry, left, right, top, top+1); + else gtk_table_attach(GTK_TABLE(table), entry, left, right, top, top+1, + GTK_FILL | GTK_EXPAND, GTK_FILL | vExpand, 2, 1); } int @@ -1074,6 +1083,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent GtkWidget *checkbutton; GtkWidget *entry; GtkWidget *hbox = NULL; + GtkWidget *pane = NULL; GtkWidget *button; GtkWidget *table; GtkWidget *spinner; @@ -1090,7 +1100,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent GtkWidget *menuBar; GtkWidget *menu; - int i, j, arraysize, left, top, height=999, width=1, boxStart; + int i, j, arraysize, left, top, height=999, width=1, boxStart, breakType = 0, r; char def[MSG_SIZ], *msg, engineDlg = (currentCps != NULL && dlgNr != BrowserDlg); if(dlgNr < PromoDlg && shellUp[dlgNr]) return 0; // already up @@ -1108,8 +1118,10 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent if(engineDlg) { // Settings popup for engine: format through heuristic int n = currentCps->nrOptions; - if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; +// if(n > 50) width = 4; else if(n>24) width = 2; else width = 1; + width = n / 20 + 1; height = n / width + 1; +printf("n=%d, h=%d, w=%d\n",n,height,width); // if(n && (currentOption[n-1].type == Button || currentOption[n-1].type == SaveButton)) currentOption[n].min = SAME_ROW; // OK on same line currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark } @@ -1140,8 +1152,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent arraysize++; } - table = gtk_table_new(arraysize, 3, FALSE); - gtk_table_set_col_spacings(GTK_TABLE(table), 20); + table = gtk_table_new(arraysize, r=TableWidth(option), FALSE); left = 0; top = -1; @@ -1149,21 +1160,32 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent if(option[i].type == -1) continue; top++; if (top >= height) { + gtk_table_resize(GTK_TABLE(table), height, r); + if(!pane) { // multi-column: put tables in intermediate hbox + if(breakType || engineDlg) + pane = gtk_hbox_new (FALSE, 0); + else + pane = gtk_vbox_new (FALSE, 0); + gtk_box_set_spacing(GTK_BOX(pane), 5 + 5*breakType); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), pane, TRUE, TRUE, 0); + } + gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); + table = gtk_table_new(arraysize - i, r=TableWidth(option + i), FALSE); top = 0; - left = left + 3; - gtk_table_resize(GTK_TABLE(table), height, left + 3); } if(!SameRow(&option[i])) { if(SameRow(&option[i+1])) { + GtkAttachOptions x = GTK_FILL; // make sure hbox is always available when we have more options on same row hbox = gtk_hbox_new (option[i].type == Button && option[i].textValue, 0); + if(!currentCps && option[i].value > 80) x |= GTK_EXPAND; // only vertically extended widgets should size vertically if (strcmp(option[i].name, "") == 0 || option[i].type == Label || option[i].type == Button) // for Label and Button name is contained inside option - gtk_table_attach_defaults(GTK_TABLE(table), hbox, left, left+3, top, top+1); + gtk_table_attach(GTK_TABLE(table), hbox, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); else - gtk_table_attach_defaults(GTK_TABLE(table), hbox, left+1, left+3, top, top+1); + gtk_table_attach(GTK_TABLE(table), hbox, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, x, 2, 1); } else hbox = NULL; //and also make sure no hbox exists if only singl option on row - } + } else top--; switch(option[i].type) { case Fractional: snprintf(def, MSG_SIZ, "%.2f", *(float*)option[i].target); @@ -1200,15 +1222,14 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent gtk_widget_set_size_request(GTK_WIDGET(sw), w, -1); textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); - gtk_widget_set_size_request(textview, -1, option[i].min); /* check if label is empty */ if (strcmp(option[i].name,"") != 0) { - gtk_table_attach_defaults(GTK_TABLE(table), label, left, left+1, top, top+1); - Pack(hbox, table, sw, left+1, left+3, top); + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); + Pack(hbox, table, sw, left+1, left+r, top, 0); } else { /* no label so let textview occupy all columns */ - Pack(hbox, table, sw, left, left+3, top); + Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); } if ( *(char**)option[i].target != NULL ) gtk_text_buffer_set_text (textbuffer, *(char**)option[i].target, -1); @@ -1237,24 +1258,24 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent gtk_entry_set_max_length (GTK_ENTRY (entry), w); // left, right, top, bottom - if (strcmp(option[i].name, "") != 0) gtk_table_attach_defaults(GTK_TABLE(table), label, left, left+1, top, top+1); - //gtk_table_attach_defaults(GTK_TABLE(table), entry, 1, 2, i, i+1); + if (strcmp(option[i].name, "") != 0) + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // leading names do not expand if (option[i].type == Spin) { spinner_adj = (GtkAdjustment *) gtk_adjustment_new (option[i].value, option[i].min, option[i].max, 1.0, 0.0, 0.0); spinner = gtk_spin_button_new (spinner_adj, 1.0, 0); - gtk_table_attach_defaults(GTK_TABLE(table), spinner, left+1, left+3, top, top+1); + gtk_table_attach(GTK_TABLE(table), spinner, left+1, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); option[i].handle = (void*)spinner; } else if (option[i].type == FileName || option[i].type == PathName) { - gtk_table_attach_defaults(GTK_TABLE(table), entry, left+1, left+2, top, top+1); + gtk_table_attach(GTK_TABLE(table), entry, left+1, left+2, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); button = gtk_button_new_with_label ("Browse"); - gtk_table_attach_defaults(GTK_TABLE(table), button, left+2, left+3, top, top+1); + gtk_table_attach(GTK_TABLE(table), button, left+2, left+r, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // Browse button does not expand g_signal_connect (button, "clicked", G_CALLBACK (BrowseGTK), (gpointer)(intptr_t) i); option[i].handle = (void*)entry; } else { - Pack(hbox, table, entry, left + (strcmp(option[i].name, "") != 0), left+3, top); + Pack(hbox, table, entry, left + (strcmp(option[i].name, "") != 0), left+r, top, 0); option[i].handle = (void*)entry; } break; @@ -1262,7 +1283,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent checkbutton = gtk_check_button_new_with_label(option[i].name); if(!currentCps) option[i].value = *(Boolean*)option[i].target; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), option[i].value); - gtk_table_attach_defaults(GTK_TABLE(table), checkbutton, left, left+3, top, top+1); + gtk_table_attach(GTK_TABLE(table), checkbutton, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 0); option[i].handle = (void *)checkbutton; break; case Label: @@ -1274,7 +1295,8 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent gtk_container_add(GTK_CONTAINER(frame), label); label = frame; } - Pack(hbox, table, label, left, left+3, top); + gtk_widget_set_size_request(label, option[i].max ? option[i].max : -1, -1); + Pack(hbox, table, label, left, left+r, top, 0); if(option[i].target) { // allow user to specify event handler for button presses gtk_widget_add_events(GTK_WIDGET(label), GDK_BUTTON_PRESS_MASK); g_signal_connect(label, "button-press-event", G_CALLBACK(MemoEvent), (gpointer) &option[i]); @@ -1298,7 +1320,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent || strstr(first.variants, VariantName(option[i].value))); } - Pack(hbox, table, button, left, left+1, top); + Pack(hbox, table, button, left, left+1, top, 0); g_signal_connect (button, "clicked", G_CALLBACK (GenericCallback), (gpointer)(intptr_t) i + (dlgNr<<16)); option[i].handle = (void*)button; break; @@ -1306,7 +1328,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent label = gtk_label_new(option[i].name); /* Left Justify */ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); - gtk_table_attach_defaults(GTK_TABLE(table), label, left, left+1, top, top+1); + gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); combobox = gtk_combo_box_new_text(); @@ -1331,7 +1353,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent //option[i].value = j + (option[i].choice[j] == NULL); gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), option[i].value); - Pack(hbox, table, combobox, left+1, left+3, top); + Pack(hbox, table, combobox, left+1, left+r, top, 0); g_signal_connect(G_OBJECT(combobox), "changed", G_CALLBACK(ComboSelect), (gpointer) (intptr_t) (i + 256*dlgNr)); option[i].handle = (void*)combobox; @@ -1361,14 +1383,14 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent gtk_widget_set_size_request(GTK_WIDGET(sw), option[i].max ? option[i].max : -1, option[i].value ? option[i].value : -1); /* never has label, so let listbox occupy all columns */ - Pack(hbox, table, sw, left, left+3, top); + Pack(hbox, table, sw, left, left+r, top, GTK_EXPAND); } break; case Graph: option[i].handle = (void*) (graph = gtk_drawing_area_new()); gtk_widget_set_size_request(graph, option[i].max, option[i].value); // gtk_drawing_area_size(graph, option[i].max, option[i].value); - gtk_table_attach_defaults(GTK_TABLE(table), graph, left, left+3, top, top+1); + gtk_table_attach_defaults(GTK_TABLE(table), graph, left, left+r, top, top+1); g_signal_connect (graph, "expose-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); gtk_widget_add_events(GTK_WIDGET(graph), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); g_signal_connect (graph, "button-press-event", G_CALLBACK (GraphEventProc), (gpointer) &option[i]); @@ -1427,14 +1449,15 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent boxStart = i; break; case BarEnd: - gtk_table_attach_defaults(GTK_TABLE(table), menuBar, left, left+1, top, top+1); + gtk_table_attach_defaults(GTK_TABLE(table), menuBar, left, left+r, top, top+1); case BoxEnd: // XtManageChildren(&form, 1); // SqueezeIntoBox(&option[boxStart], i-boxStart, option[boxStart].max); if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions break; case Break: - if(option[i].min & SAME_ROW) top = height; // force next option to start in a new column + breakType = option[i].min & SAME_ROW; + top = height; // force next option to start in a new table break; default: printf("GenericPopUp: unexpected case in switch. i=%d type=%d name=%s.\n", i, option[i].type, option[i].name); @@ -1442,8 +1465,10 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent } } - gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), - table, TRUE, TRUE, 0); + if(pane) + gtk_box_pack_start (GTK_BOX (pane), table, TRUE, TRUE, 0); + else + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), table, TRUE, TRUE, 0); /* Show dialog */ gtk_widget_show_all( dialog ); -- 1.7.0.4