core/vgui/impl/gtk2/vgui_gtk2_dialog_impl.cxx
Go to the documentation of this file.
00001 // This is core/vgui/impl/gtk2/vgui_gtk2_dialog_impl.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 // \author Philip C. Pritchett, RRG, University of Oxford
00008 // \date   28 Dec 99
00009 // \brief  See vgui_gtk2_dialog_impl.h for a description of this file.
00010 
00011 #include "vgui_gtk2_dialog_impl.h"
00012 
00013 #include <vcl_string.h>
00014 #include <vcl_vector.h>
00015 #include <vcl_iostream.h>
00016 #include <vul/vul_sprintf.h>
00017 
00018 #include <vgui/vgui_gl.h>
00019 #include <vgui/vgui_command.h>
00020 #include <vgui/internals/vgui_dialog_field.h>
00021 #include <vgui/internals/vgui_simple_field.h>
00022 #include <vgui/internals/vgui_button_field.h>
00023 #include <gtk/gtkfilesel.h>
00024 
00025 #include "vgui_gtk2_adaptor.h"
00026 
00027 static bool debug = false;
00028 
00029 static bool is_modal = true;
00030 void vgui_gtk2_dialog_impl::modal(bool m) { is_modal = m; }
00031 
00032 //--------------------------------------------------------------------------------
00033 //: Constructor
00034 vgui_gtk2_dialog_impl::vgui_gtk2_dialog_impl(const char* name)
00035   : vgui_dialog_impl(name)
00036 {
00037   title = name;
00038   ok_text = "OK";
00039   cancel_text = "Cancel";
00040 }
00041 
00042 
00043 //--------------------------------------------------------------------------------
00044 //: Destructor
00045 vgui_gtk2_dialog_impl::~vgui_gtk2_dialog_impl()
00046 {
00047 }
00048 
00049 
00050 //--------------------------------------------------------------------------------
00051 //: Make a push button widget
00052 void* vgui_gtk2_dialog_impl::pushbutton_field_widget(const char *text, const void *filename)
00053 {
00054   GtkWidget *button, *box, *image, *label;
00055 
00056   // show the image and text side by side horizontally in a box
00057   box = gtk_hbox_new(FALSE, 0);
00058 
00059   if (filename) { // this button has an image on it
00060     image = gtk_image_new_from_file((const gchar *)filename);
00061     gtk_box_pack_start(GTK_BOX(box), image, FALSE, FALSE, 3);
00062     gtk_widget_show(image);
00063   }
00064   if (text) { // this button also has text on it
00065     label = gtk_label_new(text);
00066     gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 3);
00067     gtk_widget_show(label);
00068   }
00069   gtk_widget_show(box);
00070 
00071   // Create a new button
00072   button = gtk_button_new();
00073   gtk_container_add(GTK_CONTAINER(button), box);
00074 
00075   return (void*)button;
00076 }
00077 
00078 
00079 struct vgui_gtk2_dialog_impl_choice
00080 {
00081   vcl_vector<vcl_string> names;
00082   int index;
00083 };
00084 
00085 //--------------------------------------------------------------------------------
00086 //: Make a choice widget
00087 void* vgui_gtk2_dialog_impl::choice_field_widget(const char* /*txt*/,
00088                                                  const vcl_vector<vcl_string>& labels,
00089                                                  int& val)
00090 {
00091   vgui_gtk2_dialog_impl_choice *ch = new vgui_gtk2_dialog_impl_choice;
00092   ch->names = labels;
00093   ch->index = val;
00094 
00095   return (void*)ch;
00096 }
00097 
00098 //--------------------------------------------------------------------------------
00099 //: Make a tableau widget.
00100 //
00101 // This returns a vgui_gtk2_adaptor, not a GtkWidget!
00102 void* vgui_gtk2_dialog_impl::inline_tableau_widget(const vgui_tableau_sptr tab,
00103                                                    unsigned width, unsigned height)
00104 {
00105   vgui_gtk2_adaptor *ct = new vgui_gtk2_adaptor();
00106   ct->set_tableau(tab);
00107   GtkWidget *glarea= (( vgui_gtk2_adaptor *)ct)->get_glarea_widget();
00108   gtk_widget_set_usize(glarea, width, height);
00109   gtk_widget_show(glarea);
00110 
00111   return (void*)ct;
00112 }
00113 
00114 // GTK callbacks should have C linkage
00115 extern "C" {
00116 
00117 static
00118 void accept_cb(GtkWidget* /*widget*/,
00119                gpointer   data)
00120 {
00121   if (debug) vcl_cerr << "accept\n";
00122   vgui_gtk2_dialog_impl::status_type* d = static_cast<vgui_gtk2_dialog_impl::status_type*>(data);
00123   *d = vgui_gtk2_dialog_impl::OK;
00124 }
00125 
00126 static
00127 void cancel_cb(GtkWidget* /*widget*/,
00128                gpointer data)
00129 {
00130   if (debug) vcl_cerr << "cancel\n";
00131   vgui_gtk2_dialog_impl::status_type* d = static_cast<vgui_gtk2_dialog_impl::status_type*>(data);
00132   *d = vgui_gtk2_dialog_impl::CANCEL;
00133 }
00134 
00135 static
00136 gint close_window_cb(GtkWidget* /*widget*/,
00137                      GdkEvent* /*event*/,
00138                      gpointer data)
00139 {
00140   if (debug) vcl_cerr << "close window\n";
00141   vgui_gtk2_dialog_impl::status_type* d = static_cast<vgui_gtk2_dialog_impl::status_type*>(data);
00142   *d = vgui_gtk2_dialog_impl::CLOSE;
00143   return FALSE; // propagate as necessary
00144 }
00145 
00146 struct vgui_gtk2_dialog_impl_int_pair
00147 {
00148   int* val;
00149   int tmp;
00150 };
00151 
00152 
00153 void choose_cb(GtkWidget* /*widget*/,
00154                gpointer data)
00155 {
00156   vgui_gtk2_dialog_impl_int_pair *ip = (vgui_gtk2_dialog_impl_int_pair*) data;
00157   *(ip->val) = ip->tmp;
00158   if (debug) vcl_cerr << "choose " << (ip->tmp) << '\n';
00159 }
00160 
00161 } // extern "C"
00162 
00163 void vgui_gtk2_dialog_impl::set_ok_button(const char* txt)
00164 {
00165   if (txt)
00166     ok_text = vcl_string(txt);
00167   else
00168     ok_text = vcl_string("REMOVEBUTTON");
00169 }
00170 
00171 void vgui_gtk2_dialog_impl::set_cancel_button(const char* txt)
00172 {
00173   if (txt)
00174     cancel_text = vcl_string(txt);
00175   else
00176     cancel_text = vcl_string("REMOVEBUTTON");
00177 }
00178 
00179 extern "C" {
00180 
00181 struct file_ok_data
00182 {
00183   GtkFileSelection* filew;
00184   GtkEntry* file_entry;
00185 };
00186 
00187 //--------------------------------------------------------------------------------
00188 //: Gets the file selection for the file browser.
00189 void ok_file_browse(file_ok_data* data)
00190 {
00191   gtk_entry_set_text( data->file_entry,
00192                       gtk_file_selection_get_filename(data->filew) );
00193   gtk_widget_destroy( GTK_WIDGET(data->filew) );
00194   delete data;
00195 }
00196 
00197 //--------------------------------------------------------------------------------
00198 //: Cancels the file selection
00199 void cancel_file_browse(file_ok_data* data)
00200 {
00201   gtk_widget_destroy( GTK_WIDGET(data->filew) );
00202   delete data;
00203 }
00204 
00205 //--------------------------------------------------------------------------------
00206 
00207 void browse_files(GtkWidget* /*w*/, GtkEntry* file_entry)
00208 {
00209   GtkFileSelection* filew = GTK_FILE_SELECTION( gtk_file_selection_new ("File selection") );
00210 
00211   file_ok_data* data = new file_ok_data;
00212   data->filew = filew;
00213   data->file_entry = file_entry;
00214 
00215   gtk_signal_connect_object (GTK_OBJECT(filew->cancel_button), "clicked",
00216                              (GtkSignalFunc) cancel_file_browse, (GtkObject*)(data));
00217   gtk_signal_connect_object (GTK_OBJECT(filew->ok_button), "clicked",
00218                              (GtkSignalFunc) ok_file_browse, (GtkObject*)(data));
00219 
00220   gtk_file_selection_set_filename (filew, gtk_entry_get_text(file_entry));
00221 
00222   // Hide buttons for create directory, delete and rename file:
00223   gtk_file_selection_hide_fileop_buttons(filew);
00224 
00225   gtk_window_set_modal(GTK_WINDOW(filew), is_modal);
00226   gtk_widget_show( GTK_WIDGET(filew) );
00227 }
00228 
00229 //-------------------------------------------------------------------------------
00230 //: Handles a change of color.
00231 // Done by passing the value back to the (hidden) text entry in the dialog box.
00232 void color_changed_cb(GtkColorSelection *colorsel, GtkEntry* color_entry) {
00233   // Get the color from the color chooser (r,g,b,a):
00234   gdouble color[4];
00235   gtk_color_selection_get_color(colorsel, color);
00236 
00237   vul_sprintf color_str("%.3f %.3f %.3f", color[0], color[1], color[2]);
00238 
00239   // Set the text entry back in the dialog to the color selected in the color chooser:
00240   gtk_entry_set_text(GTK_ENTRY(color_entry), color_str.c_str());
00241 }
00242 
00243 
00244 struct cancel_color_data
00245 {
00246   vcl_string* orig_color;
00247   GtkEntry* color_entry;
00248   GtkColorSelectionDialog* colord;
00249 };
00250 
00251 //-------------------------------------------------------------------------------
00252 //: Handles OK button on color chooser.
00253 // by closing the dialog window and releasing memory.
00254 void ok_color_chooser(cancel_color_data* data) {
00255   gtk_widget_destroy(GTK_WIDGET(data->colord));
00256   delete data->orig_color;
00257   delete data;
00258 }
00259 
00260 //-------------------------------------------------------------------------------
00261 //: Handles cancel button on color chooser.
00262 // by resetting the color to its original value, shutting down the color
00263 // chooser and passing control back to the dialog.
00264 void cancel_color_chooser(cancel_color_data* data) {
00265   gtk_entry_set_text(GTK_ENTRY(data->color_entry), data->orig_color->c_str());
00266 
00267   gtk_widget_destroy(GTK_WIDGET(data->colord));
00268   delete data->orig_color;
00269   delete data;
00270 }
00271 
00272 //-------------------------------------------------------------------------------
00273 //: Display a colour chooser.
00274 void choose_color(GtkWidget* /*w*/, GtkEntry* color_entry)
00275 {
00276   GtkColorSelectionDialog* colord = GTK_COLOR_SELECTION_DIALOG( gtk_color_selection_dialog_new("Select color") );
00277   gtk_widget_hide( GTK_WIDGET(colord->help_button) );
00278 
00279   cancel_color_data* data = new cancel_color_data;
00280   data->orig_color = new vcl_string(gtk_entry_get_text(GTK_ENTRY(color_entry)));
00281   data->color_entry = color_entry;
00282   data->colord = colord;
00283 
00284   gtk_signal_connect(GTK_OBJECT(colord->colorsel), "color_changed",
00285                      (GtkSignalFunc)color_changed_cb, color_entry);
00286   gtk_signal_connect_object (GTK_OBJECT(colord->cancel_button), "clicked",
00287                              (GtkSignalFunc)cancel_color_chooser, (GtkObject*)data);
00288   gtk_signal_connect_object (GTK_OBJECT(colord->ok_button), "clicked",
00289                              (GtkSignalFunc)ok_color_chooser, (GtkObject*)data);
00290 
00291   gtk_window_set_modal(GTK_WINDOW(colord), is_modal);
00292   gtk_widget_show(GTK_WIDGET(colord));
00293 }
00294 
00295 } // extern "C"
00296 
00297 //-------------------------------------------------------------------------------
00298 //: Display the dialog box.
00299 bool vgui_gtk2_dialog_impl::ask()
00300 {
00301   GtkWidget* dialog = gtk_dialog_new();
00302 
00303   gtk_window_set_title(GTK_WINDOW(dialog), title.c_str());
00304   gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
00305   gtk_window_set_modal(GTK_WINDOW(dialog), is_modal);
00306 
00307   if (ok_text.compare("REMOVEBUTTON"))
00308   {
00309     GtkWidget *accept = gtk_button_new_with_label (ok_text.c_str());
00310     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
00311                        accept, TRUE, TRUE, 0);
00312     gtk_signal_connect(GTK_OBJECT(accept), "clicked",
00313                        GTK_SIGNAL_FUNC(accept_cb),
00314                        &dialog_status_);
00315     gtk_widget_show(accept);
00316   }
00317   if (cancel_text.compare("REMOVEBUTTON"))
00318   {
00319     GtkWidget *cancel = gtk_button_new_with_label (cancel_text.c_str());
00320     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
00321                      cancel, TRUE, TRUE, 0);
00322     gtk_signal_connect(GTK_OBJECT(cancel), "clicked",
00323                        GTK_SIGNAL_FUNC(cancel_cb),
00324                        &dialog_status_);
00325     gtk_widget_show(cancel);
00326   }
00327 
00328   // closing the dialog box is equivalent to canceling.
00329   //
00330   gtk_signal_connect(GTK_OBJECT(dialog), "delete_event",
00331                      GTK_SIGNAL_FUNC(close_window_cb),
00332                      &dialog_status_);
00333 
00334   // list of widgets used to extract values
00335   vcl_vector<GtkWidget*> wlist;
00336 
00337   // to delete the adaptors associated with inline tableaux
00338   vcl_vector<vgui_gtk2_adaptor*> adaptor_list;
00339 
00340   // to delete the file selection dialog for the inline selection
00341   vcl_vector<GtkWidget*> delete_wlist;
00342 
00343   // true if there is "line_break" element in the dialog.
00344   bool has_line_break = false;
00345   GtkWidget* current_hbox = 0;
00346 
00347   // traverse the dialog elements to see if there is a line_break.
00348   for (vcl_vector<element>::iterator e_iter = elements.begin();
00349        e_iter != elements.end(); ++e_iter) {
00350     element l = *e_iter;
00351     if ( l.type == line_br ) {
00352       if (debug) vcl_cerr << "The dialog has line_br\n";
00353       has_line_break = true;
00354       current_hbox = gtk_hbox_new(FALSE, 6);
00355       break;
00356     }
00357   }
00358 
00359   for (vcl_vector<element>::iterator e_iter = elements.begin();
00360        e_iter != elements.end(); ++e_iter) {
00361 
00362     element l = *e_iter;
00363     vgui_dialog_field *field = l.field;
00364 
00365     GtkWidget* entry;
00366 
00367     if (l.type == int_elem ||
00368         l.type == long_elem ||
00369         l.type == float_elem ||
00370         l.type == double_elem ||
00371         l.type == string_elem) {
00372 
00373       GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
00374       GtkWidget* label = gtk_label_new(field->label.c_str());
00375       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
00376 
00377       entry = gtk_entry_new_with_max_length(50);
00378       gtk_entry_set_text(GTK_ENTRY(entry), l.field->current_value().c_str());
00379 
00380       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
00381       gtk_box_pack_end(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
00382 
00383       if ( has_line_break )
00384         gtk_box_pack_start(GTK_BOX(current_hbox), hbox, TRUE, TRUE, 0);
00385       else
00386         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
00387 
00388       gtk_widget_show(label);
00389       gtk_widget_show(entry);
00390       gtk_widget_show(hbox);
00391       wlist.push_back(entry);
00392     }
00393     else if (l.type == bool_elem) {
00394       vgui_bool_field *field = static_cast<vgui_bool_field*>(l.field);
00395       entry = gtk_check_button_new_with_label(field->label.c_str());
00396       gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(entry), field->var);
00397       if ( has_line_break )
00398         gtk_box_pack_start(GTK_BOX(current_hbox), entry, TRUE, TRUE, 0);
00399       else
00400         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), entry, TRUE, TRUE, 0);
00401       gtk_widget_show(entry);
00402       wlist.push_back(entry);
00403     }
00404     else if (l.type == choice_elem) {
00405       vgui_int_field *field = static_cast<vgui_int_field*>(l.field);
00406 
00407       GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
00408       GtkWidget* label = gtk_label_new(field->label.c_str());
00409       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
00410 
00411       entry = gtk_option_menu_new();
00412       GtkWidget* menu = gtk_menu_new();
00413 
00414 
00415       vgui_gtk2_dialog_impl_choice *ch = (vgui_gtk2_dialog_impl_choice*)l.widget;
00416 
00417       int count = 0;
00418       for (vcl_vector<vcl_string>::iterator s_iter =  ch->names.begin();
00419            s_iter != ch->names.end(); ++s_iter, ++count) {
00420 
00421         GtkWidget* item = gtk_menu_item_new_with_label(s_iter->c_str());
00422         gtk_widget_show(item);
00423         gtk_menu_append(GTK_MENU(menu), item);
00424 
00425         vgui_gtk2_dialog_impl_int_pair *ip = new vgui_gtk2_dialog_impl_int_pair;
00426         ip->val = &(ch->index);
00427         ip->tmp = count;
00428 
00429         gtk_signal_connect(GTK_OBJECT(item), "activate",
00430                            GTK_SIGNAL_FUNC(choose_cb), ip);
00431       }
00432 
00433       gtk_option_menu_set_menu(GTK_OPTION_MENU(entry), menu);
00434       gtk_option_menu_set_history(GTK_OPTION_MENU(entry), field->var);
00435 
00436       gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
00437       gtk_box_pack_start(GTK_BOX(hbox), entry, FALSE, FALSE, 5);
00438       if ( has_line_break )
00439         gtk_box_pack_start(GTK_BOX(current_hbox), hbox, TRUE, TRUE, 0);
00440       else
00441         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
00442 
00443       gtk_widget_show(label);
00444       gtk_widget_show(entry);
00445       gtk_widget_show(hbox);
00446       wlist.push_back(entry);
00447     }
00448     else if (l.type == text_msg) {
00449       GtkWidget* label = gtk_label_new(field->label.c_str());
00450       if ( has_line_break )
00451         gtk_box_pack_start(GTK_BOX(current_hbox), label, TRUE, TRUE, 0);
00452       else
00453         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 0);
00454       gtk_widget_show(label);
00455       wlist.push_back(entry);
00456     }
00457     else if (l.type == file_bsr){
00458       GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
00459       GtkWidget* label = gtk_label_new(field->label.c_str());
00460       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
00461       GtkWidget* button = gtk_button_new_with_label("Choose file...");
00462       GtkWidget* entry = gtk_entry_new_with_max_length(150);
00463       gtk_entry_set_text(GTK_ENTRY(entry), l.field->current_value().c_str());
00464 
00465       gtk_signal_connect (GTK_OBJECT (button), "clicked",
00466                           GTK_SIGNAL_FUNC (browse_files), (gpointer)entry);
00467       gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
00468       gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
00469       gtk_box_pack_start(GTK_BOX(hbox), button,TRUE,TRUE, 0);
00470 
00471       if ( has_line_break )
00472         gtk_box_pack_start(GTK_BOX(current_hbox), hbox, TRUE, TRUE, 0);
00473       else
00474         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
00475       gtk_widget_show(label);
00476       gtk_widget_show(entry);
00477       gtk_widget_show(button);
00478       gtk_widget_show(hbox);
00479       wlist.push_back(entry);
00480     }
00481     else if (l.type == inline_file_bsr) {
00482       // This is a complete hack. To get an "inline" browser, we
00483       // generate a file browser dialog, but "steal" the main box to
00484       // display within the current dialog. We cannot embed the file
00485       // browser in this dialog because the latter is a top level
00486       // window. However, we must make sure we delete this file
00487       // browser widget when we close this dialog, so we have to keep
00488       // an extra list of "auxiliary widgets to delete".
00489       //
00490       // This is ugly. A better solution would be most welcome.
00491 
00492       GtkWidget* filew = gtk_file_selection_new ("File selection");
00493       gtk_file_selection_set_filename (GTK_FILE_SELECTION(filew),
00494                                        l.field->current_value().c_str());
00495 
00496       // Hide buttons for create directory, delete and rename file:
00497       gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(filew));
00498       // Hide Ok and Cancel buttons
00499       gtk_widget_hide(GTK_FILE_SELECTION(filew)->ok_button);
00500       gtk_widget_hide(GTK_FILE_SELECTION(filew)->cancel_button);
00501 
00502       GtkWidget* file_main_vbox = GTK_FILE_SELECTION(filew)->main_vbox;
00503 
00504       gtk_widget_ref( file_main_vbox );
00505       gtk_container_remove( GTK_CONTAINER(filew), file_main_vbox);
00506       if ( has_line_break )
00507         gtk_box_pack_start(GTK_BOX(current_hbox), file_main_vbox, TRUE, TRUE, 0);
00508       else
00509         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), file_main_vbox, TRUE, TRUE, 0);
00510       gtk_widget_unref( file_main_vbox );
00511 
00512       gtk_widget_show( file_main_vbox );
00513       wlist.push_back(filew);
00514       delete_wlist.push_back(filew);
00515     }
00516     else if (l.type == color_csr){
00517       GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
00518       GtkWidget* label = gtk_label_new(field->label.c_str());
00519       gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
00520       GtkWidget* button = gtk_button_new_with_label("Choose color...");
00521       GtkWidget* entry = gtk_entry_new_with_max_length(50);
00522       gtk_entry_set_text(GTK_ENTRY(entry), l.field->current_value().c_str());
00523 
00524       gtk_signal_connect (GTK_OBJECT (button), "clicked",
00525                           GTK_SIGNAL_FUNC (choose_color), entry);
00526       gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
00527       gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
00528       gtk_box_pack_start(GTK_BOX(hbox), button, TRUE, TRUE, 0);
00529       if ( has_line_break )
00530         gtk_box_pack_start(GTK_BOX(current_hbox), hbox, TRUE, TRUE, 0);
00531       else
00532         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
00533 
00534       gtk_widget_show(label);
00535       gtk_widget_show(entry);
00536       gtk_widget_show(button);
00537       gtk_widget_show(hbox);
00538       wlist.push_back(entry);
00539     }
00540     else if (l.type == inline_color_csr) {
00541       GtkWidget* colorw = gtk_color_selection_new();
00542       GtkWidget* color_entry = gtk_entry_new_with_max_length(50);
00543 
00544       gtk_entry_set_text(GTK_ENTRY(color_entry),
00545                          l.field->current_value().c_str());
00546       gtk_signal_connect(GTK_OBJECT(colorw), "color_changed",
00547                          (GtkSignalFunc)color_changed_cb, color_entry);
00548 
00549       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), colorw, TRUE,
00550                          TRUE, 0);
00551       gtk_widget_show(colorw);
00552 
00553       // Connect the color entry text field to the dialog so that the
00554       // widget will be automatically destroyed.
00555       if ( has_line_break )
00556         gtk_box_pack_start(GTK_BOX(current_hbox), color_entry, TRUE, TRUE, 0);
00557       else
00558         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), color_entry, TRUE,
00559                          TRUE, 0);
00560       gtk_widget_hide(color_entry);
00561       wlist.push_back(color_entry);
00562     }
00563     else if (l.type == inline_tabl) {
00564       vgui_gtk2_adaptor* adapt = static_cast<vgui_gtk2_adaptor*>(l.widget);
00565       GtkWidget* widg = adapt->get_glarea_widget();
00566       GtkWidget* hbox = gtk_hbox_new(FALSE, 10);
00567 
00568       gtk_box_pack_start(GTK_BOX(hbox), widg, TRUE, TRUE, 0);
00569       if ( has_line_break )
00570         gtk_box_pack_start(GTK_BOX(current_hbox), hbox, TRUE, TRUE, 0);
00571       else
00572         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, TRUE, TRUE, 0);
00573       gtk_widget_show(hbox);
00574       wlist.push_back(widg);
00575       adaptor_list.push_back( adapt );
00576     }
00577     else if (l.type == line_br ) {
00578       gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), current_hbox, TRUE, TRUE, 0);
00579       gtk_widget_show(current_hbox);
00580       current_hbox = gtk_hbox_new(FALSE, 6);
00581     }
00582     else if (l.type == button_elem) {
00583       vgui_button_field *field = static_cast<vgui_button_field*>(l.field);
00584       GtkWidget *button = static_cast<GtkWidget*>(l.widget);
00585       gtk_widget_show(button);
00586 
00587       // Connect the "clicked" signal to the callback function
00588       vgui_command_cfunc *cmndc = static_cast<vgui_command_cfunc*>((field->cmnd).ptr());
00589       g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(cmndc->fn), NULL);
00590 
00591       if ( has_line_break )
00592         gtk_box_pack_start(GTK_BOX(current_hbox), button, TRUE, TRUE, 0);
00593       else
00594         gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), button, TRUE, TRUE, 0);
00595     }
00596     else
00597       vcl_cerr << "Unknown type = " << int(l.type) << '\n';
00598   }
00599 
00600   gtk_widget_show(dialog);
00601 
00602   dialog_status_ = BUSY;
00603 
00604   while ( dialog_status_ == BUSY ) {
00605     gtk_main_iteration();
00606   }
00607 
00608   // At this point, the adaptors of the inline tableaux have performed
00609   // their duties. No further signals should go to this adaptor since
00610   // the associated glarea should be destroyed by the time this
00611   // function call ends. That is, by the time further iterations of
00612   // the gtk main loop occur.
00613   for ( vcl_vector<vgui_gtk2_adaptor*>::iterator iter = adaptor_list.begin();
00614         iter != adaptor_list.end(); ++iter ) {
00615     delete *iter;
00616   }
00617 
00618   //gtk_signal_disconnect(GTK_OBJECT(dialog), destroy_handler_id);
00619 
00620   bool ret_value = false;
00621   if (dialog_status_ == CLOSE) {
00622     // the window was closed without pressing any buttons. The windows will be destroyed, etc, so
00623     // we don't need to worry about anything.
00624   }
00625   else if (dialog_status_ == OK)  // OK button has been pressed
00626   {
00627     vcl_vector<GtkWidget*>::iterator w_iter = wlist.begin();
00628     for (vcl_vector<element>::iterator e_iter = elements.begin();
00629          e_iter != elements.end(); ++e_iter, ++w_iter) {
00630       element l = *e_iter;
00631 
00632       if ( l.type == line_br ) { // skip line break
00633         --w_iter;
00634         continue;
00635       }
00636 
00637       if (l.type == int_elem ||
00638           l.type == long_elem ||
00639           l.type == float_elem ||
00640           l.type == double_elem ||
00641           l.type == string_elem ||
00642           l.type == file_bsr ||
00643           l.type == color_csr ||
00644           l.type == inline_color_csr) {
00645         GtkWidget *input = *w_iter;
00646         l.field->update_value(gtk_entry_get_text(GTK_ENTRY(input)));
00647       }
00648       if (l.type == inline_file_bsr)
00649         l.field->update_value(gtk_file_selection_get_filename(GTK_FILE_SELECTION(*w_iter)));
00650 
00651       if (l.type == bool_elem) {
00652         vgui_bool_field *field = static_cast<vgui_bool_field*>(l.field);
00653         GtkWidget *input = *w_iter;
00654         field->var = (bool) gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(input));
00655       }
00656       if (l.type == choice_elem) {
00657         vgui_int_field *field = static_cast<vgui_int_field*>(l.field);
00658         vgui_gtk2_dialog_impl_choice *ch = static_cast<vgui_gtk2_dialog_impl_choice*>(l.widget);
00659         field->var = ch->index;
00660       }
00661     }
00662     // Need to flush GL events if we have a tableau field, otherwise it crashes:
00663     glFlush();
00664     gtk_widget_destroy(dialog);
00665 
00666     ret_value = true;
00667   }
00668   else // Cancel button has been pressed
00669   {
00670     gtk_widget_destroy(dialog);
00671   }
00672 
00673   // Destroy widgets that weren't inserted into this dialog
00674   for ( vcl_vector<GtkWidget*>::iterator iter = delete_wlist.begin();
00675         iter != delete_wlist.end(); ++iter ) {
00676     gtk_widget_destroy( *iter );
00677   }
00678 
00679   return ret_value;
00680 }