1    | /***************************************
2    |   $Header: /cvsroot/petscgraphics/chui.c,v 1.9 2003/08/04 14:14:47 hazelsct Exp $
3    | 
4    |   This is a Glade front end to the little phase field/fluid structure
5    |   interactions program based on PETSc, but can serve as a front end to a
6    |   variety of PETSc programs with minor adjustments.
7    | 
8    |   Callback functions are grouped here according to where they appear in the
9    |   main window (except on_run_clicked is below main window items), then the run
10   |   control dialog, and save dialog.
11   | 
12   |   I haven't put function comments in to keep the line count down, the functions
13   |   are generally pretty simple GTK+ callbacks.
14   | ***************************************/
15   | 
16   | 
17   | /*  */
18   | 
19   | #include <gtk/gtk.h>
20   | #include <glade/glade.h>
21   | #include <stdio.h>
22   | #include <math.h>
23   | 
24   | GladeXML *xml;
25   | FILE *simulation_input_file, *simulation_output_file;
26   | 
27   | /* Simple debugging macro */
28   | #ifdef DEBUG
29   | #define DPRINTF printf
30   | #else
31   | #define DPRINTF(fmt...)
32   | #endif
33   | 
34   | /* Discretization stuff */
35   | double Lx;
36   | int nx;
37   | 
38   | void on_width_changed (GtkWidget *width, gpointer user_data) {
39   |   gchar *entrytext;
40   |   entrytext = gtk_entry_get_text (GTK_ENTRY (width));
41   |   sscanf (entrytext, "%lf", &Lx);
42   |   DPRINTF ("Width set to %g\n", Lx); }
43   | 
44   | void on_resolution_changed (GtkWidget *resolution, gpointer user_data) {
45   |   /* Note: gtk_spin_button_get_value_as_int doesn't respond to typed entry */
46   |   /* nx = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (resolution)); */
47   |   gchar *entrytext;
48   |   entrytext = gtk_entry_get_text (GTK_ENTRY (resolution));
49   |   sscanf (entrytext, "%d", &nx);
50   |   DPRINTF ("Resolution set to %d\n", nx); }
51   | 
52   | /* Timestep stuff */
53   | double dt, dt_factor, dt_max;
54   | int last_tstep;
55   | 
56   | void on_timestep_changed (GtkWidget *timestep, gpointer user_data) {
57   |   gchar *entrytext;
58   |   entrytext = gtk_entry_get_text (GTK_ENTRY (timestep));
59   |   sscanf (entrytext, "%lf", &dt);
60   |   DPRINTF ("Timestep set to %g\n", dt); }
61   | 
62   | void on_time_factor_changed (GtkWidget *time_factor, gpointer user_data) {
63   |   gchar *entrytext;
64   |   entrytext = gtk_entry_get_text (GTK_ENTRY (time_factor));
65   |   sscanf (entrytext, "%lf", &dt_factor);
66   |   DPRINTF ("Time factor set to %g\n", dt_factor); }
67   | 
68   | void on_max_timestep_changed (GtkWidget *max_timestep, gpointer user_data) {
69   |   gchar *entrytext;
70   |   entrytext = gtk_entry_get_text (GTK_ENTRY (max_timestep));
71   |   sscanf (entrytext, "%lf", &dt_max);
72   |   DPRINTF ("Max timestep set to %g\n", dt_max); }
73   | 
74   | void on_last_timestep_changed (GtkWidget *last_timestep, gpointer user_data) {
75   |   gchar *entrytext;
76   |   entrytext = gtk_entry_get_text (GTK_ENTRY (last_timestep));
77   |   sscanf (entrytext, "%d", &last_tstep);
78   |   DPRINTF ("Last timestep set to %d\n", last_tstep); }
79   | 
80   | /* Display stuff */
81   | gboolean display_x, display_text;
82   | 
83   | void on_xdisplay_toggled (GtkWidget *xdisplay, gpointer user_data) {
84   |   display_x = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (xdisplay));
85   |   DPRINTF (display_x ? "Using X display\n" : "Not using X display\n"); }
86   | 
87   | void on_textdisplay_toggled (GtkWidget *textdisplay, gpointer user_data) {
88   |   display_text = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(textdisplay));
89   |   DPRINTF(display_text ? "Using text display\n" : "Not using text display\n");}
90   | 
91   | /* Remote host stuff */
92   | gboolean remote_host;
93   | gchar *remote_hostname, thetransport[50];
94   | 
95   | void on_remote_check_toggled (GtkWidget *remote_check, gpointer user_data) {
96   |   if (remote_host = gtk_toggle_button_get_active
97   |       (GTK_TOGGLE_BUTTON (remote_check))) {
98   |     gtk_widget_set_sensitive
99   |       (glade_xml_get_widget (xml, "transport_label"), TRUE);
100  |     gtk_widget_set_sensitive
101  |       (glade_xml_get_widget (xml, "transport_options"), TRUE);
102  |     gtk_widget_set_sensitive
103  |       (glade_xml_get_widget (xml, "remote_host_label"), TRUE);
104  |     gtk_widget_set_sensitive
105  |       (glade_xml_get_widget (xml, "remote_host"), TRUE); }
106  |   else {
107  |     gtk_widget_set_sensitive
108  |       (glade_xml_get_widget (xml, "transport_label"), FALSE);
109  |     gtk_widget_set_sensitive
110  |       (glade_xml_get_widget (xml, "transport_options"), FALSE);
111  |     gtk_widget_set_sensitive
112  |       (glade_xml_get_widget (xml, "remote_host_label"), FALSE);
113  |     gtk_widget_set_sensitive
114  |       (glade_xml_get_widget (xml, "remote_host"), FALSE); }
115  |   DPRINTF (remote_host ? "Using remote host\n" : "Using local host\n"); }
116  | 
117  | void on_ssh_item_activate (GtkWidget *widget, gpointer user_data) {
118  |   sprintf (thetransport, "ssh");
119  |   DPRINTF ("Transport type = %s\n", thetransport); }
120  | 
121  | void on_rsh_item_activate (GtkWidget *widget, gpointer user_data) {
122  |   sprintf (thetransport, "rsh");
123  |   DPRINTF ("Transport type = %s\n", thetransport); }
124  | 
125  | void on_remote_host_changed (GtkWidget *remote_host, gpointer user_data) {
126  |   remote_hostname = gtk_entry_get_text (GTK_ENTRY (remote_host));
127  |   DPRINTF ("Remote host set to %s\n", remote_hostname); }
128  | 
129  | /* MPI stuff */
130  | gchar *mpirun_command;
131  | int number_cpus;
132  | 
133  | void on_mpirun_changed (GtkWidget *mpirun, gpointer user_data) {
134  |   mpirun_command = gtk_entry_get_text (GTK_ENTRY (mpirun));
135  |   DPRINTF ("MPIrun command set to %s\n", mpirun_command); }
136  | 
137  | void on_num_cpus_changed (GtkWidget *num_cpus, gpointer user_data) {
138  |   /* Note: gtk_spin_button_get_value_as_int doesn't respond to typed entry */
139  |   /* nx = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (num_cpus)); */
140  |   gchar *entrytext;
141  |   entrytext = gtk_entry_get_text (GTK_ENTRY (num_cpus));
142  |   sscanf (entrytext, "%d", &number_cpus);
143  |   if (number_cpus > 1) {
144  |     gtk_widget_set_sensitive
145  |       (glade_xml_get_widget (xml, "mpirun_label"), TRUE);
146  |     gtk_widget_set_sensitive
147  |       (glade_xml_get_widget (xml, "mpirun"), TRUE); }
148  |   else {
149  |     gtk_widget_set_sensitive
150  |       (glade_xml_get_widget (xml, "mpirun_label"), FALSE);
151  |     gtk_widget_set_sensitive
152  |       (glade_xml_get_widget (xml, "mpirun"), FALSE); }
153  |   DPRINTF ("Num_CPUs set to %d\n", number_cpus); }
154  | 
155  | /* Dimensionality */
156  | gboolean twodee;
157  | 
158  | void on_2d_activate (GtkWidget *unused, gpointer user_data) {
159  |   twodee = TRUE; DPRINTF ("Simulating in two dimensions\n"); }
160  | 
161  | void on_3d_activate (GtkWidget *unused, gpointer user_data) {
162  |   twodee = FALSE; DPRINTF ("Simulating in three dimensions\n"); }
163  | 
164  | /* Load and save (unfinished!) */
165  | void on_load_ok_clicked (GtkWidget *load_file, gpointer user_data) {
166  |   gtk_widget_hide (load_file); }
167  | 
168  | void on_save_ok_clicked (GtkWidget *save_file, gpointer user_data) {
169  |   gtk_widget_hide (save_file); }
170  | 
171  | /* Toggle buttons */
172  | void on_show_options_toggled (GtkWidget *options_notebook, gpointer user_data){
173  |   if (gtk_toggle_button_get_active
174  |       (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_options"))))
175  |     gtk_widget_show (options_notebook);
176  |   else
177  |     gtk_widget_hide (options_notebook); }
178  | 
179  | void on_show_output_toggled (GtkWidget *output_window, gpointer user_data) {
180  |   if (gtk_toggle_button_get_active
181  |       (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_output"))))
182  |     gtk_widget_show (output_window);
183  |   else
184  |     gtk_widget_hide (output_window); }
185  | 
186  | /* The run button! */
187  | gint pipe_input_tag; /* Tag number for gdk_input_add/remove */
188  | 
189  | /* First an ancillary function to read from the pipe and write to the window */
190  | void read_simulation_data (gpointer user_data, gint source,
191  | 			   GdkInputCondition condition)
192  | {
193  |   int i, len;
194  |   gfloat residual;
195  |   char simulation_input [200];
196  |   gchar start[50], current[50], final[50];
197  |   static GtkWidget *output_text=NULL,
198  |     *timestep_progressbar, *start_timestep, *current_timestep, *final_timestep,
199  |     *newton_progressbar, *start_newton, *current_newton, *final_newton,
200  |     *gcr_progressbar, *start_gcr, *current_gcr, *final_gcr;
201  |   static gfloat orig_gcr=0., orig_newton=0., tol_gcr=5.0E-4, tol_newton=5.0E-4;
202  |   static int orig_timestep = 0;
203  |   void on_stop_clicked (GtkWidget *, gpointer);
204  | 
205  |   if (output_text == NULL) {
206  |     output_text = glade_xml_get_widget (xml, "output_text");
207  |     timestep_progressbar = glade_xml_get_widget (xml, "timestep_progressbar");
208  |     start_timestep = glade_xml_get_widget (xml, "start_timestep");
209  |     current_timestep = glade_xml_get_widget (xml, "current_timestep");
210  |     final_timestep = glade_xml_get_widget (xml, "final_timestep");
211  |     newton_progressbar = glade_xml_get_widget (xml, "newton_progressbar");
212  |     start_newton = glade_xml_get_widget (xml, "start_newton");
213  |     current_newton = glade_xml_get_widget (xml, "current_newton");
214  |     final_newton = glade_xml_get_widget (xml, "final_newton");
215  |     gcr_progressbar = glade_xml_get_widget (xml, "gcr_progressbar");
216  |     start_gcr = glade_xml_get_widget (xml, "start_gcr");
217  |     current_gcr = glade_xml_get_widget (xml, "current_gcr");
218  |     final_gcr = glade_xml_get_widget (xml, "final_gcr"); }
219  | 
220  |   /* Read text until end-of-line */
221  |   if (fgets (simulation_input, sizeof (simulation_input),
222  | 	     simulation_input_file) != NULL) {
223  | 
224  |     /* KSP residual */
225  |     if (!(strncmp (simulation_input+4, "KSP", 3)) ||
226  | 	!(strncmp (simulation_input+5, "KSP", 3)) ||
227  | 	!(strncmp (simulation_input+6, "KSP", 3)) ||
228  | 	!(strncmp (simulation_input+7, "KSP", 3)) ||
229  | 	!(strncmp (simulation_input+8, "KSP", 3))) {
230  |       /* Get current GCR residual, set orig and final if necessary */
231  |       sscanf (simulation_input, "%d KSP Residual norm %f", &i, &residual);
232  |       sprintf (current, "%.4e", residual);
233  |       gtk_label_set_text (GTK_LABEL (current_gcr), current);
234  |       if (i == 0) {
235  | 	orig_gcr = residual;
236  | 	tol_gcr = residual * 1.e-5;
237  | 	sprintf (start, "%.4e", orig_gcr);
238  | 	gtk_label_set_text (GTK_LABEL (start_gcr), start);
239  | 	sprintf (final, "%.4e", tol_gcr);
240  | 	gtk_label_set_text (GTK_LABEL (final_gcr), final); }
241  | 
242  |       /* Reset when falls below tolerance (it's done), plot progress */
243  |       if (residual < tol_gcr)
244  | 	residual = orig_gcr;
245  |       if (residual <= orig_gcr)
246  | 	gtk_progress_bar_update (GTK_PROGRESS_BAR (gcr_progressbar),
247  | 				 (gfloat) log(orig_gcr/residual) /
248  | 				 log(orig_gcr/tol_gcr)); }
249  | 
250  |     /* Newton residual */
251  |     else if (!(strncmp (simulation_input+4, "SNES", 4)) ||
252  | 	!(strncmp (simulation_input+5, "SNES", 4)) ||
253  | 	!(strncmp (simulation_input+6, "SNES", 4))) {
254  |       /* Reset GCR orig and progress bar */
255  |       orig_gcr = 0.0;
256  |       gtk_progress_bar_update (GTK_PROGRESS_BAR (gcr_progressbar),
257  | 			       (gfloat) 0.0);
258  |       /* Get current Newton residual, set orig and final if necessary */
259  |       sscanf (simulation_input, "%d SNES Function norm %f", &i, &residual);
260  |       sprintf (current, "%.4e", residual);
261  |       gtk_label_set_text (GTK_LABEL (current_newton), current);
262  |       if (i == 0) {
263  | 	orig_newton = residual;
264  | 	tol_newton = residual * 1.e-8;
265  | 	sprintf (start, "%.4e", orig_newton);
266  | 	gtk_label_set_text (GTK_LABEL (start_newton), start);
267  | 	sprintf (final, "%.4e", tol_newton);
268  | 	gtk_label_set_text (GTK_LABEL (final_newton), final); }
269  | 
270  |       /* Reset when falls below tolerance (it's done), plot progress */
271  |       if (residual < tol_newton)
272  | 	residual = orig_newton;
273  |       if (residual <= orig_newton)
274  | 	gtk_progress_bar_update (GTK_PROGRESS_BAR (newton_progressbar),
275  | 				 (gfloat) log(orig_newton/residual) /
276  | 				 log(orig_newton/tol_newton)); }
277  | 
278  |     /* Timestep */
279  |     else if (!(strncmp (simulation_input, "timestep", 8))) {
280  |       sscanf (simulation_input, "timestep %d", &i);
281  |       sprintf (current, "%d", i);
282  |       gtk_label_set_text (GTK_LABEL (current_timestep), current);
283  |       if (i == 0) {
284  | 	sprintf (current, "%d", last_tstep);
285  | 	gtk_label_set_text (GTK_LABEL (final_timestep), current); }
286  |       gtk_progress_bar_update (GTK_PROGRESS_BAR (timestep_progressbar),
287  | 			       (gfloat) i/last_tstep); }
288  | 
289  |     /* End of simulation */
290  |     else if (!(strncmp (simulation_input, "Game over", 9)))
291  |       on_stop_clicked
292  | 	(glade_xml_get_widget (xml, "run_control_frame"), NULL);
293  | 
294  |     /* Write the text to the output widget in the run dialog */
295  |     else
296  |       gtk_text_insert (GTK_TEXT (output_text), NULL, NULL, NULL,
297  | 		       simulation_input, strlen (simulation_input)); }
298  | }
299  |   
300  | 
301  | #define MAX_COMMAND_LINE_OPTIONS 22
302  | 
303  | int from_simulation_pipe[2], to_simulation_pipe[2];
304  | 
305  | void on_run_clicked (GtkWidget *run_control_frame, gpointer user_data) {
306  |   gchar command_line [MAX_COMMAND_LINE_OPTIONS][50],
307  |     clinestr [MAX_COMMAND_LINE_OPTIONS*50];
308  |   int simulation_pid;
309  |   int command = 0, i;
310  | 
311  |   /* Font: -misc-fixed-medium-r-semicondensed-*-*-110-c-*-iso10646-1, or
312  |      -misc-fixed-medium-r-normal-*-*-80-*-*-c-*-iso10646-1 (or 70) */
313  | 
314  |   /* Construct the command line string, of special and standard options */
315  |   if (remote_host) {
316  |     strcpy (command_line[command++], thetransport);
317  |     if (!strcmp (thetransport, "ssh"))
318  |       sprintf (command_line[command++], "-AX");
319  |     strcpy (command_line[command++], remote_hostname); }
320  |   if (number_cpus > 1) {
321  |     sprintf (command_line[command++], "%s", mpirun_command);
322  |     sprintf (command_line[command++], "-np");
323  |     sprintf (command_line[command++], "%d", number_cpus); }
324  |   /* Note that if we add to this list, we must also modify the COMMAND_LINE
325  |      macros above, and also the execlp command below. */
326  |   sprintf (command_line[command], CHTS_PATH);
327  |   strcat (command_line[command++], "/chts");
328  |   sprintf (command_line[command++], "-ts_max_steps");
329  |   sprintf (command_line[command++], "%d", last_tstep);
330  |   sprintf (command_line[command++], "-mx");
331  |   sprintf (command_line[command++], "%d", nx);
332  |   sprintf (command_line[command++], "-my");
333  |   sprintf (command_line[command++], "%d", nx);
334  |   sprintf (command_line[command++], "-mz");
335  |   sprintf (command_line[command++], "%d", nx);
336  |   sprintf (command_line[command++], "-dt");
337  |   sprintf (command_line[command++], "%e", dt);
338  |   if (!display_x)
339  |     sprintf (command_line[command++], "-no_contours");
340  |   if (twodee)
341  |     sprintf (command_line[command++], "-twodee");
342  |   sprintf (command_line[command++], "-ts_monitor");
343  |   sprintf (command_line[command++], "-snes_monitor");
344  |   sprintf (command_line[command++], "-ksp_monitor");
345  | 
346  |   while (command < MAX_COMMAND_LINE_OPTIONS)
347  |     command_line [command++][0] = '\0';
348  |   sprintf (clinestr, "Command line:");
349  |   for (command = 0;
350  |        command < MAX_COMMAND_LINE_OPTIONS && command_line [command][0];
351  |        command++)
352  |     sprintf (clinestr+strlen(clinestr), " %s", command_line [command]);
353  |   sprintf (clinestr+strlen(clinestr), "\n");
354  |   DPRINTF ("%s", clinestr);
355  |   gtk_text_insert (GTK_TEXT (glade_xml_get_widget (xml, "output_text")), NULL,
356  | 		   NULL, NULL, clinestr, strlen (clinestr));
357  | 
358  |   /* Try to spawn a new simulation process.  Most of this was shamelessly
359  |      ripped from Ken Brakke's Surface Evolver. */
360  |   pipe (from_simulation_pipe); /* from simulation stdout */
361  |   pipe (to_simulation_pipe); /* to simulation stdin */
362  |   simulation_pid = fork ();
363  | 
364  |   if(simulation_pid==0) { /* child */
365  |     close (0);
366  |     dup (to_simulation_pipe[0]);
367  |     close (to_simulation_pipe[0]);
368  |     close (to_simulation_pipe[1]);
369  |     close (1);
370  |     dup (from_simulation_pipe[1]);
371  |     close (from_simulation_pipe[0]);
372  |     close (from_simulation_pipe[1]);
373  | 
374  |     /* Change to the correct directory */
375  |     /* if (chdir ("/home/hazelsct/davidch/oscsolid")) {
376  |        perror (command_line[0]); exit (1); } */
377  | 
378  |     /* signal(SIGINT,SIG_IGN); */
379  |     /* Okay, so this is a retarded way to do it... :-) */
380  |     execlp(command_line[0], command_line[0], command_line[1], command_line[2],
381  | 	   command_line[3], command_line[4], command_line[5], command_line[6],
382  | 	   command_line[7], command_line[8], command_line[9], command_line[10],
383  | 	   command_line[11],command_line[12],command_line[13],command_line[14],
384  | 	   command_line[15],command_line[16],command_line[17],command_line[18],
385  | 	   command_line[19],command_line[20],command_line[21],NULL);
386  |     perror (command_line[0]); /* only error gets here */
387  |     exit (1);
388  |   }
389  | 
390  |   /* Chui program execution resumes here */
391  |   close (from_simulation_pipe[1]);
392  |   close (to_simulation_pipe[0]);
393  | 
394  |   /* simulation_input_file is hooked to stdout of simulation */
395  |   simulation_input_file = fdopen (from_simulation_pipe[0], "r");
396  |   /* simulation_output_file is hooked to stdin of simulation */
397  |   simulation_output_file = fdopen (to_simulation_pipe[1], "w");
398  | 
399  |   /* Sensitize and desensitize various widgets */
400  |   gtk_widget_set_sensitive
401  |     (glade_xml_get_widget (xml, "options_notebook"), FALSE);
402  |   gtk_widget_set_sensitive
403  |     (glade_xml_get_widget (xml, "load"), FALSE);
404  |   gtk_widget_set_sensitive
405  |     (glade_xml_get_widget (xml, "save"), FALSE);
406  |   gtk_widget_set_sensitive
407  |     (glade_xml_get_widget (xml, "run"), FALSE);
408  |   gtk_widget_set_sensitive
409  |     (glade_xml_get_widget (xml, "pause"), TRUE);
410  |   gtk_widget_set_sensitive
411  |     (glade_xml_get_widget (xml, "stop"), TRUE);
412  | 
413  |   /* Show the run control table and text output window */
414  |   /* gtk_widget_show (run_control_frame); */
415  |   if (!(gtk_toggle_button_get_active
416  | 	(GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_output"))))) {
417  |     gtk_toggle_button_set_active
418  |       (GTK_TOGGLE_BUTTON (glade_xml_get_widget (xml, "show_output")), TRUE);
419  |     gtk_widget_show (glade_xml_get_widget (xml, "output_window")); }
420  | 
421  |   /* Add the input function, this will have gtk_main() call
422  |      read_simulation_data() when input is received on the pipe. */
423  |   pipe_input_tag = gdk_input_add (from_simulation_pipe [0], GDK_INPUT_READ,
424  | 				  read_simulation_data, NULL);
425  | }
426  | 
427  | void on_stop_clicked (GtkWidget *run_control_frame, gpointer user_data) {
428  |   /* This should really send some kind of "stop" signal to chts and wait for a
429  |      reply... interactive options setting, etc. */
430  | 
431  |   /* Remove the pipe sensitivity and close the files and pipes */
432  |   gdk_input_remove (pipe_input_tag);
433  |   fclose (simulation_input_file);
434  |   fclose (simulation_output_file);
435  |   close (from_simulation_pipe [0]);
436  |   close (to_simulation_pipe [1]);
437  | 
438  |   /* Make appropriate widget readjustments */
439  |   /* gtk_widget_hide (run_control_frame); */
440  |   gtk_widget_set_sensitive
441  |     (glade_xml_get_widget (xml, "options_notebook"), TRUE);
442  |   gtk_widget_set_sensitive
443  |     (glade_xml_get_widget (xml, "load"), TRUE);
444  |   gtk_widget_set_sensitive
445  |     (glade_xml_get_widget (xml, "save"), TRUE);
446  |   gtk_widget_set_sensitive
447  |     (glade_xml_get_widget (xml, "run"), TRUE);
448  |   gtk_widget_set_sensitive
449  |     (glade_xml_get_widget (xml, "pause"), FALSE);
450  |   gtk_widget_set_sensitive
451  |     (glade_xml_get_widget (xml, "stop"), FALSE); }
452  | 
453  | /* Does nothing for now */
454  | void on_pause_clicked (GtkWidget *forgot, gpointer user_data) {
455  |   return; }
456  | 
457  | /* And finally, main() */
458  | int main (int argc, char *argv[])
459  | {
460  |   gchar buff[200];
461  |   GtkWidget *transport_options, *transport_menu, *ssh_item, *rsh_item,
462  |     *dimension_options, *dimension_menu;
463  | 
464  |   /* Basic init stufff */
465  |   gtk_init(&argc, &argv);
466  |   glade_init();
467  | 
468  |   /* Load the interface, display the initial window, and connect the signals */
469  |   strncpy (buff, GLADE_DIRECTORY, 187);
470  |   strcat (buff, "/chui.glade");
471  |   xml = glade_xml_new (buff, NULL);
472  |   glade_xml_signal_autoconnect (xml);
473  | 
474  |   /* For some reason, option menus don't quite work in Glade, so I had to make
475  |      a popup menu and attach it to the option menu */
476  |   transport_options = glade_xml_get_widget (xml, "transport_options");
477  |   gtk_option_menu_remove_menu (GTK_OPTION_MENU (transport_options));
478  |   transport_menu = glade_xml_get_widget (xml, "transport_menu");
479  |   gtk_option_menu_set_menu (GTK_OPTION_MENU(transport_options),transport_menu);
480  |   gtk_widget_show (transport_menu);
481  |   dimension_options = glade_xml_get_widget (xml, "dimension_options");
482  |   gtk_option_menu_remove_menu (GTK_OPTION_MENU (dimension_options));
483  |   dimension_menu = glade_xml_get_widget (xml, "dimension_menu");
484  |   gtk_option_menu_set_menu (GTK_OPTION_MENU(dimension_options),dimension_menu);
485  |   gtk_widget_show (dimension_menu);
486  | 
487  |   /* Call handlers to set initial values from Glade defaults */
488  |   on_width_changed (glade_xml_get_widget (xml, "width"), NULL);
489  |   on_resolution_changed (glade_xml_get_widget (xml, "resolution"), NULL);
490  |   on_timestep_changed (glade_xml_get_widget (xml, "timestep"), NULL);
491  |   on_time_factor_changed (glade_xml_get_widget (xml, "time_factor"), NULL);
492  |   on_max_timestep_changed (glade_xml_get_widget (xml, "max_timestep"), NULL);
493  |   on_last_timestep_changed (glade_xml_get_widget (xml, "last_timestep"), NULL);
494  |   on_xdisplay_toggled (glade_xml_get_widget (xml, "xdisplay"), NULL);
495  |   on_textdisplay_toggled (glade_xml_get_widget (xml, "textdisplay"), NULL);
496  |   on_remote_check_toggled (glade_xml_get_widget (xml, "remote_check"), NULL);
497  |   on_ssh_item_activate (NULL, NULL);
498  |   on_remote_host_changed (glade_xml_get_widget (xml, "remote_host"), NULL);
499  |   on_mpirun_changed (glade_xml_get_widget (xml, "mpirun"), NULL);
500  |   on_num_cpus_changed (glade_xml_get_widget (xml, "num_cpus"), NULL);
501  |   on_3d_activate (NULL, NULL);
502  | 
503  |   /* Off we go! */
504  |   gtk_main();
505  | 
506  |   return 0;
507  | }