Back to index

gcompris  8.2.2
board_config.c
Go to the documentation of this file.
00001 /* gcompris - board_config.c
00002  *
00003  * Time-stamp: <2006/08/21 23:27:57 bruno>
00004  *
00005  * Copyright (C) 2001 Pascal Georges
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020  */
00021 
00022 #include <string.h>
00023 
00024 #include "gcompris.h"
00025 
00026 #define COMBOBOX_COL_MAX 15
00027 
00028 static GcomprisBoard *config_board;
00029 
00030 void
00031 gc_board_config_start(GcomprisBoard *aBoard, GcomprisProfile *aProfile)
00032 {
00033 
00034   if (aBoard->plugin == NULL){
00035     g_warning("gc_board_config_start: board %s/%s is not initialised ? Hummmm...", aBoard->section,aBoard->name);
00036     return;
00037   }
00038 
00039   if (aBoard->plugin->config_start == NULL) {
00040     g_warning("Trying to configure board %s/%s without config_start", aBoard->section,aBoard->name);
00041     return;
00042   }
00043 
00044   config_board = aBoard;
00045 
00046   aBoard->plugin->config_start(aBoard, aProfile);
00047   return;
00048 }
00049 
00050 
00051   
00052 void
00053 gc_board_config_stop()
00054 {
00055   if (!config_board)
00056     return;
00057 
00058   config_board->plugin->config_stop();
00059 
00060   config_board = NULL;
00061   return;
00062 }
00063 
00064 static GtkWindow *conf_window = NULL;
00065 static GtkVBox *main_conf_box = NULL;
00066 static GHashTable *hash_conf = NULL;
00067 static GcomprisConfCallback Confcallback = NULL;
00068 static gchar *label_markup = NULL;
00069 
00070 
00071 static void
00072 check_key(gchar *key)
00073 {
00074   if ((strcmp(key, "locale") == 0) ||
00075       (strcmp(key, "locale_sound") == 0) ||
00076       (strcmp(key, "wordlist") == 0))
00077     g_error(" Key %s forbiden ! Change !", key);
00078 }
00079 
00080 void
00081 gc_board_conf_close (GtkDialog *dialog,
00082                    gpointer   user_data)
00083 {
00084   gtk_object_destroy(GTK_OBJECT(dialog));
00085   g_hash_table_destroy (hash_conf);
00086   hash_conf = NULL;
00087 
00088   /* in case we close without response */
00089   if (Confcallback){
00090     Confcallback(NULL);
00091     Confcallback = NULL;
00092   }
00093 
00094   g_free(label_markup);
00095 }
00096 
00097 void
00098 _response_board_conf (GtkButton *button,
00099                     gint arg1,
00100                     gpointer user_data)
00101 {
00102 
00103   if (Confcallback){
00104 
00105     switch (arg1){
00106     case GTK_RESPONSE_APPLY:
00107       Confcallback(hash_conf);
00108       break;
00109     case GTK_RESPONSE_CANCEL:
00110       Confcallback(NULL);
00111       break;
00112     case GTK_RESPONSE_NONE:
00113       Confcallback(NULL);
00114       break;
00115     default:
00116       Confcallback(NULL);
00117       break;
00118     }
00119 
00120     Confcallback = NULL;
00121   }
00122 
00123   gc_board_conf_close (GTK_DIALOG(conf_window), NULL);
00124 
00125 }
00126 
00127 #ifdef XF86_VIDMODE
00128 static GdkEventConfigure last_configure_event;
00129 
00130 static gint
00131 _conf_window_configured(GtkWindow *window,
00132                      GdkEventConfigure *event, gpointer param)
00133 {
00134   gint new_x, new_y;
00135   double screen_width, screen_height;
00136   /* Because we call gtk_window_move, we cause a configure event. Filter out
00137      identical events to avoid looping. */
00138   if (memcmp(&last_configure_event, event, sizeof(GdkEventConfigure)))
00139   {
00140     gnome_canvas_get_scroll_region( GNOME_CANVAS( gtk_bin_get_child( GTK_BIN(
00141       gc_get_window()))), NULL, NULL, &screen_width, &screen_height);
00142     /* strange but gcompris.c sets the scrollheight to screen_height + 30 */
00143     screen_height -= 30;
00144     new_x = ((gint)screen_width - event->width) / 2;
00145     new_y = ((gint)screen_height - event->height) / 2;
00146     /* printf("screen %dx%d, window %dx%d, place %dx%d\n", (int)screen_width, (int)screen_height, event->width, event->height, new_x, new_y); */
00147     gtk_window_move (conf_window, new_x, new_y);
00148     memcpy(&last_configure_event, event, sizeof(GdkEventConfigure));
00149   }
00150 
00151   /* Act as if we aren't there / aren't hooked up */
00152   return FALSE;
00153 }
00154 #endif
00155 
00156 GtkVBox *
00157 gc_board_config_window_display(gchar *label, GcomprisConfCallback callback)
00158 {
00159   GtkWidget *header;
00160  
00161   /* init static values or callbacks */
00162   Confcallback = callback;
00163   hash_conf = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
00164   
00165   /* Creating a config window will cause our main window to loose focus,
00166      this tells the main window to ignore the next focus out event (and thus
00167      stay in fullscreen mode if we're fullscreen). */
00168   gc_ignore_next_focus_out();
00169 
00170   /* main configuration window */
00171   conf_window = \
00172     GTK_WINDOW(gtk_dialog_new_with_buttons ("GCompris",
00173                                        GTK_WINDOW(gtk_widget_get_toplevel (GTK_WIDGET(gc_board_get_current()->canvas))),
00174                                        GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
00175                                        GTK_STOCK_CANCEL,
00176                                        GTK_RESPONSE_CANCEL,
00177                                        GTK_STOCK_APPLY,
00178                                        GTK_RESPONSE_APPLY,
00179                                        NULL));
00180   
00181 
00182   /* parameters */
00183 #ifdef XF86_VIDMODE
00184   if (gc_prop_get()->fullscreen &&
00185       !gc_prop_get()->noxf86vm)   
00186     {
00187       memset(&last_configure_event, 0, sizeof(GdkEventConfigure));
00188       gtk_widget_add_events(GTK_WIDGET(conf_window), GDK_STRUCTURE_MASK);
00189       gtk_signal_connect (GTK_OBJECT (conf_window), "configure_event",
00190         GTK_SIGNAL_FUNC (_conf_window_configured), 0);
00191     }
00192   else
00193 #endif
00194       gtk_window_set_position (conf_window,
00195                                GTK_WIN_POS_CENTER_ALWAYS);
00196 
00197   gtk_widget_show(GTK_WIDGET(conf_window));
00198 
00199   GcomprisProperties *properties = gc_prop_get();
00200   if (properties->fullscreen && !properties->noxf86vm)
00201     if (gdk_pointer_grab(gc_get_window()->window, TRUE, 0,
00202                       gc_get_window()->window, NULL, GDK_CURRENT_TIME) !=
00203        GDK_GRAB_SUCCESS)
00204       g_warning("Pointer grab failed");
00205 
00206   /* main vbox in window */
00207   main_conf_box = GTK_VBOX(GTK_DIALOG(conf_window)->vbox);
00208 
00209   g_signal_connect(G_OBJECT(conf_window), 
00210                  "response",
00211                  G_CALLBACK(_response_board_conf),
00212                  NULL);
00213 
00214   g_signal_connect (G_OBJECT(conf_window),
00215                   "close",
00216                   G_CALLBACK(gc_board_conf_close),
00217                   NULL);
00218 
00219   
00220 
00221   /* Label header */
00222   header = gtk_label_new ((gchar *)NULL);
00223   gtk_widget_show(header);
00224   gtk_box_pack_start (GTK_BOX(main_conf_box),
00225                     header,
00226                     FALSE,
00227                     FALSE,
00228                     0);
00229 
00230   gtk_label_set_justify (GTK_LABEL(header),
00231                       GTK_JUSTIFY_CENTER);
00232   
00233   label_markup = g_strdup_printf("<span size='large'>%s</span>",label);
00234   gtk_label_set_markup (GTK_LABEL(header),
00235                         (const gchar *)label_markup);
00236 
00237   gc_board_conf_separator();
00238   
00239   return main_conf_box;
00240 }
00241 
00242 void 
00243 gc_board_conf_boolean_box_toggled (GtkToggleButton *togglebutton,
00244                            gpointer key)
00245 {
00246   gchar *the_key = g_strdup((gchar *)key);
00247   gchar *value;
00248   
00249   if (gtk_toggle_button_get_active (togglebutton))
00250     value = g_strdup("True");
00251   else
00252     value = g_strdup("False");
00253   
00254   g_hash_table_replace(hash_conf, (gpointer) the_key, (gpointer) value);
00255 }
00256 
00257 GtkCheckButton *
00258 gc_board_config_boolean_box(const gchar *label, gchar *key, gboolean initial_value)
00259 {
00260   check_key( key);
00261 
00262   GtkWidget *CheckBox = gtk_check_button_new_with_label (label);
00263 
00264   gtk_widget_show(CheckBox);
00265 
00266   gtk_box_pack_start (GTK_BOX(main_conf_box),
00267                     CheckBox,
00268                     FALSE,
00269                     FALSE,
00270                     0);
00271 
00272   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(CheckBox),
00273                             initial_value);
00274 
00275   g_signal_connect   (G_OBJECT(CheckBox),
00276                     "toggled",
00277                     G_CALLBACK(gc_board_conf_boolean_box_toggled),
00278                     key);
00279 
00280   return GTK_CHECK_BUTTON(CheckBox);
00281 }
00282 
00283 /* code get from gtk */
00284 /* included here to not depend on gtk 2.6 */
00285 
00286 static gchar *
00287 _get_active_text (GtkComboBox *combo_box)
00288 {
00289   GtkTreeIter iter;
00290   gchar *text = NULL;
00291 
00292   g_return_val_if_fail (GTK_IS_LIST_STORE (gtk_combo_box_get_model (combo_box)), NULL);
00293 
00294   if (gtk_combo_box_get_active_iter (combo_box, &iter))
00295     gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter, 
00296                      0, &text, -1);
00297 
00298   return text;
00299 }
00300 
00301 static void
00302 _combo_box_changed(GtkComboBox *combobox,
00303                  gpointer key)
00304 {
00305   gchar *the_key = g_strdup((gchar *)key);
00306 
00307   gchar *value = g_strdup_printf("%s", _get_active_text (combobox));
00308   
00309   g_hash_table_replace(hash_conf, (gpointer) the_key, (gpointer) value);
00310 }
00311 
00312 static inline int my_strcmp(gchar *a, gchar *b) { return strcmp( a, b); }
00313 
00314 
00315 GtkComboBox *gc_board_config_combo_box(const gchar *label, GList *strings, gchar *key, gchar *init)
00316 {
00317   check_key( key);
00318 
00319   GtkWidget *combobox;
00320   GtkWidget *hbox = gtk_hbox_new (FALSE, 8);
00321   GList *list;
00322   GtkWidget *label_combo;
00323   gint init_index = 0;
00324 
00325   if (init)
00326     init_index =  g_list_position ( strings, g_list_find_custom ( strings,(gconstpointer)  init, (GCompareFunc) my_strcmp));
00327   
00328   if (init_index < 0)
00329     init_index=0;
00330 
00331   gtk_widget_show(hbox);
00332   
00333   gtk_box_pack_start (GTK_BOX(main_conf_box),
00334                     hbox,
00335                     FALSE,
00336                     FALSE,
00337                     0);
00338 
00339   /* Label */
00340   label_combo = gtk_label_new ((gchar *)NULL);
00341   gtk_widget_show(label_combo);
00342   gtk_box_pack_start (GTK_BOX(hbox),
00343                     label_combo,
00344                     FALSE,
00345                     FALSE,
00346                     0);
00347 
00348   gtk_label_set_justify (GTK_LABEL(label_combo),
00349                       GTK_JUSTIFY_RIGHT);
00350 
00351   gtk_label_set_markup (GTK_LABEL(label_combo),
00352                         (const gchar *)label);
00353 
00354 
00355   combobox = gtk_combo_box_new_text();
00356 
00357   gtk_widget_show(combobox);
00358 
00359   gtk_box_pack_start (GTK_BOX(hbox),
00360                     combobox,
00361                     FALSE,
00362                     FALSE,
00363                     0);
00364 
00365 
00366   for (list = strings; list != NULL; list = list->next)
00367     gtk_combo_box_append_text       (GTK_COMBO_BOX(combobox),
00368                                  list->data);
00369 
00370   if (g_list_length(strings) > COMBOBOX_COL_MAX)
00371     gtk_combo_box_set_wrap_width    (GTK_COMBO_BOX(combobox),
00372             g_list_length(strings) / COMBOBOX_COL_MAX +1 );
00373   
00374   gtk_combo_box_set_active (GTK_COMBO_BOX(combobox),
00375                          init_index);
00376   
00377   g_signal_connect(G_OBJECT(combobox),
00378                  "changed",
00379                  G_CALLBACK(_combo_box_changed),
00380                  key);
00381 
00382   return GTK_COMBO_BOX(combobox);
00383 }
00384 
00385 static GSList *radio_group = NULL;
00386 static GtkWidget *radio_box;
00387 static gchar *radio_key = NULL;
00388 static gchar *radio_text = NULL;
00389 static gchar *radio_init = NULL;
00390 
00391 static void radio_changed(GtkToggleButton *togglebutton,
00392                        gpointer key)
00393 {
00394   gboolean state = gtk_toggle_button_get_active (togglebutton);
00395   gchar *h_key;
00396   gchar *h_value;
00397 
00398   if (state){
00399     h_key = g_strdup (radio_key);
00400     h_value = g_strdup((gchar *) key);
00401     g_hash_table_replace (hash_conf, h_key, h_value);
00402   }
00403 }
00404 
00405 static void
00406 create_radio_buttons(gpointer key,
00407                    gpointer value,
00408                    gpointer hash_radio)
00409 {
00410   GtkWidget *radio_button;
00411   gchar *key_copy;
00412 
00413   radio_button = gtk_radio_button_new_with_label (radio_group,
00414                                             (const gchar *) g_strdup(value));
00415 
00416   gtk_box_pack_start (GTK_BOX (radio_box), radio_button, TRUE, TRUE, 2);
00417   
00418   gtk_widget_show (GTK_WIDGET (radio_button));
00419   
00420   radio_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (radio_button));
00421   
00422   key_copy = g_strdup ((gchar *)key);
00423 
00424   if (strcmp( key_copy, radio_init)==0)
00425     gtk_toggle_button_set_active    (GTK_TOGGLE_BUTTON(radio_button),TRUE);
00426 
00427   g_signal_connect(G_OBJECT(radio_button), 
00428                  "toggled", 
00429                  G_CALLBACK(radio_changed), 
00430                  (gpointer) key_copy);
00431   
00432   g_hash_table_replace ( hash_radio, (gpointer) key_copy, (gpointer) radio_button);
00433 }
00434 
00435 static void
00436 destroy_hash (GtkObject *object,
00437              gpointer hash_table)
00438 {
00439   g_hash_table_destroy((GHashTable *)hash_table);
00440   radio_group = NULL;
00441   g_free(radio_text);
00442   g_free(radio_key);
00443   g_free(radio_init);
00444 }
00445 
00446 GHashTable *
00447 gc_board_config_radio_buttons(const gchar *label,
00448                      gchar *key,
00449                      GHashTable *buttons_label,
00450                      gchar *init)
00451 {
00452   check_key( key);
00453 
00454   GtkWidget *radio_label;
00455 
00456   GHashTable *buttons = g_hash_table_new_full (g_str_hash,
00457                                           g_str_equal,
00458                                           g_free,
00459                                           NULL);
00460 
00461   radio_box = gtk_vbox_new (TRUE, 2);
00462   gtk_widget_show (GTK_WIDGET (radio_box));
00463 
00464   gtk_box_pack_start (GTK_BOX(main_conf_box),
00465                     radio_box,
00466                     FALSE,
00467                     FALSE,
00468                     0);
00469 
00470   radio_label = gtk_label_new ((gchar *)NULL);
00471   gtk_widget_show(radio_label);
00472 
00473   gtk_box_pack_start (GTK_BOX(radio_box),
00474                     radio_label,
00475                     FALSE,
00476                     FALSE,
00477                     0);
00478 
00479   gtk_label_set_justify (GTK_LABEL(radio_label),
00480                       GTK_JUSTIFY_CENTER);
00481   
00482   radio_text = g_strdup(label);
00483   gtk_label_set_markup (GTK_LABEL(radio_label),
00484                         (const gchar *)radio_text);
00485 
00486   radio_key = g_strdup(key);
00487   radio_init = g_strdup(init);
00488 
00489   g_hash_table_foreach( buttons_label, 
00490                      (GHFunc) create_radio_buttons,
00491                      (gpointer) buttons);
00492 
00493   g_signal_connect (G_OBJECT(radio_box), "destroy", G_CALLBACK(destroy_hash), (gpointer) buttons);
00494 
00495   return buttons;
00496 }
00497 
00498 static void
00499 spin_changed (GtkSpinButton *spinbutton,
00500              gpointer key)
00501 {
00502   gchar *h_key = g_strdup((gchar *) key);
00503   gchar *h_value = g_strdup_printf("%d",gtk_spin_button_get_value_as_int (spinbutton));
00504 
00505   g_hash_table_replace (hash_conf, h_key, h_value);
00506 }
00507 
00508 GtkSpinButton *
00509 gc_board_config_spin_int(const gchar *label, gchar *key, gint min, gint max, gint step, gint init)
00510 {
00511   check_key( key);
00512 
00513   GtkWidget *spin;
00514   GtkWidget *hbox = gtk_hbox_new (FALSE, 8);
00515   GtkWidget *label_spin;
00516 
00517   gtk_widget_show(hbox);
00518 
00519   gtk_box_pack_start (GTK_BOX(main_conf_box),
00520                     hbox,
00521                     FALSE,
00522                     FALSE,
00523                     0);
00524 
00525   /* Label */
00526   label_spin = gtk_label_new ((gchar *)NULL);
00527   gtk_widget_show(label_spin);
00528   gtk_box_pack_start (GTK_BOX(hbox),
00529                     label_spin,
00530                     FALSE,
00531                     FALSE,
00532                     0);
00533 
00534   gtk_label_set_justify (GTK_LABEL(label_spin),
00535                       GTK_JUSTIFY_RIGHT);
00536 
00537   gtk_label_set_markup (GTK_LABEL(label_spin),
00538                         (const gchar *)label);
00539 
00540   spin = gtk_spin_button_new_with_range  ((gdouble )min,
00541                                      (gdouble )max,
00542                                           (gdouble )step);
00543   gtk_widget_show(spin);
00544   gtk_box_pack_start (GTK_BOX(hbox),
00545                     spin,
00546                     FALSE,
00547                     FALSE,
00548                     0);
00549 
00550   gtk_spin_button_set_wrap ( GTK_SPIN_BUTTON(spin), TRUE);
00551   gtk_spin_button_set_numeric ( GTK_SPIN_BUTTON(spin), TRUE);
00552   gtk_spin_button_set_digits ( GTK_SPIN_BUTTON(spin), 0);
00553 
00554   gtk_spin_button_set_value ( GTK_SPIN_BUTTON(spin), (gdouble) init);
00555 
00556   g_signal_connect (G_OBJECT(spin), 
00557                   "value-changed",
00558                   G_CALLBACK(spin_changed),
00559                   key);
00560 
00561   return GTK_SPIN_BUTTON(spin);
00562 
00563 }
00564 
00565 GtkHSeparator *
00566 gc_board_conf_separator()
00567 {
00568   GtkWidget *separator = gtk_hseparator_new ();
00569 
00570   gtk_widget_show(separator);
00571 
00572   gtk_box_pack_start (GTK_BOX(main_conf_box),
00573                     separator,
00574                     FALSE,
00575                     FALSE,
00576                     8);
00577 
00578   return GTK_HSEPARATOR(separator);
00579 
00580 }
00581 
00582 /***********************************************/
00583 /* L10n                                        */
00584 /***********************************************/
00585 
00594 GList*
00595 gc_locale_gets_list(){
00596 
00597   static GList *gcompris_locales_list = NULL;
00598 
00599   GcomprisProperties *properties = gc_prop_get();
00600   GDir   *textdomain_dir;
00601   GError **error = NULL;
00602   GList  *locales = NULL;
00603 
00604   if(gcompris_locales_list)
00605     return(gcompris_locales_list);
00606 
00607   /* There is no english locale but it exists anyway */
00608   locales = g_list_append(locales, g_strdup("en"));
00609 
00610   textdomain_dir = g_dir_open (properties->package_locale_dir, 0, error);
00611   const gchar *fname;
00612   gchar *fname_abs;
00613   gchar *catalog;
00614   
00615   while ((fname = g_dir_read_name(textdomain_dir))) {
00616     fname_abs = g_strdup_printf("%s/%s", properties->package_locale_dir, fname);
00617     if (!g_file_test(fname_abs, G_FILE_TEST_IS_DIR))
00618       continue;
00619 
00620     catalog = g_strdup_printf("%s/LC_MESSAGES/gcompris.mo", fname_abs);
00621 
00622     if (g_file_test(catalog, G_FILE_TEST_EXISTS)){
00623       locales = g_list_append(locales, g_strdup(fname));
00624     }
00625     g_free (fname_abs);
00626     g_free(catalog);
00627   }
00628 
00629   g_dir_close (textdomain_dir);
00630 
00631   /* Save it for next call */
00632   gcompris_locales_list = locales;
00633 
00634   return locales;
00635 }
00636 
00637 
00638 void 
00639 gc_board_config_combo_locales_changed(GtkComboBox *combobox,
00640                             gpointer key)
00641 {
00642   gchar *the_key = g_strdup((gchar *)key);
00643   gchar *value;
00644   gint index = gtk_combo_box_get_active (combobox);
00645 
00646   if (index == 0)
00647     /* Default value of gcompris selected */
00648     value = g_strdup ("NULL");
00649   else
00650     value = _get_active_text (combobox);
00651 
00652   g_hash_table_replace(hash_conf, (gpointer) the_key, (gpointer) value);
00653 }
00654 
00655 /* key = "locale" */
00656 GtkComboBox*
00657 gc_board_config_combo_locales(gchar *init)
00658 {
00659 
00660   GtkWidget *combobox;
00661   GtkWidget *hbox = gtk_hbox_new (FALSE, 8);
00662   GList *list, *strings;
00663   GtkWidget *label_combo;
00664   gint init_index = 0;
00665 
00666   strings = gc_locale_gets_list();
00667 
00668   strings = g_list_prepend( strings, _("Default"));
00669 
00670   if (init)
00671     init_index = g_list_position(strings,
00672                              g_list_find_custom(strings,
00673                                               (gconstpointer) init,
00674                                               (GCompareFunc) my_strcmp));
00675 
00676   if (init_index < 0)
00677     init_index=0;
00678   
00679   gtk_widget_show(hbox);
00680   
00681   gtk_box_pack_start (GTK_BOX(main_conf_box),
00682                     hbox,
00683                     FALSE,
00684                     FALSE,
00685                     0);
00686 
00687   /* Label */
00688   label_combo = gtk_label_new ((gchar *)NULL);
00689   gtk_widget_show(label_combo);
00690   gtk_box_pack_start (GTK_BOX(hbox),
00691                     label_combo,
00692                     FALSE,
00693                     FALSE,
00694                     0);
00695 
00696   gtk_label_set_justify (GTK_LABEL(label_combo),
00697                       GTK_JUSTIFY_RIGHT);
00698 
00699   gtk_label_set_markup (GTK_LABEL(label_combo),
00700                         _("Select the language\n to use in the board"));
00701 
00702   combobox = gtk_combo_box_new_text();
00703 
00704   gtk_widget_show(combobox);
00705 
00706   gtk_box_pack_start (GTK_BOX(hbox),
00707                     combobox,
00708                     FALSE,
00709                     FALSE,
00710                     0);
00711 
00712 
00713   for (list = strings; list != NULL; list = list->next)
00714     gtk_combo_box_append_text       (GTK_COMBO_BOX(combobox),
00715                                  list->data);
00716 
00717   if (g_list_length(strings) > COMBOBOX_COL_MAX)
00718     gtk_combo_box_set_wrap_width    (GTK_COMBO_BOX(combobox),
00719             g_list_length(strings) / COMBOBOX_COL_MAX +1 );
00720   
00721   gtk_combo_box_set_active (GTK_COMBO_BOX(combobox),
00722                          init_index);
00723   
00724   g_signal_connect(G_OBJECT(combobox),
00725                  "changed",
00726                  G_CALLBACK(gc_board_config_combo_locales_changed),
00727                  "locale");
00728 
00729   return GTK_COMBO_BOX(combobox);
00730 
00731 }
00732 
00733 static gchar *current_locale = NULL;
00734 void
00735 gc_locale_change(gchar *locale)
00736 {
00737   if (!locale)
00738     return;
00739 
00740   if (strcmp(locale, "NULL") == 0){
00741     gc_locale_reset();
00742     return;
00743   }
00744 
00745   current_locale = g_strdup(gc_locale_get());
00746 
00747   gc_locale_set(locale);
00748 }
00749 
00750 void
00751 gc_locale_reset()
00752 {
00753   if (current_locale == NULL)
00754     return;
00755 
00756   gc_locale_change(current_locale);
00757 
00758   g_free(current_locale);
00759   current_locale = NULL;
00760 }
00761 
00762 
00771 GList*
00772 gc_locale_gets_asset_list(const gchar *filename)
00773 {
00774   GList *locales, *list, *locales_asset = NULL;
00775   gchar *abs_filename;
00776 
00777   locales = gc_locale_gets_list();
00778 
00779   for (list = locales; list != NULL; list = list->next)
00780     { 
00781       gchar **tmp;
00782 
00783       /* Check there is a $LOCALE to replace */
00784       if((tmp = g_strsplit(filename, "$LOCALE", -1)))
00785        {
00786          gchar locale[6];
00787          gchar *filename2;
00788 
00789          /* try with the locale */
00790          g_strlcpy(locale, list->data, sizeof(locale));
00791          filename2 = g_strjoinv(locale, tmp);
00792          g_warning("trying locale file '%s'\n", filename2);
00793          abs_filename = gc_file_find_absolute(filename2);
00794          g_free(filename2);
00795 
00796          g_strfreev(tmp);
00797        }
00798       else
00799        {
00800          abs_filename = gc_file_find_absolute(filename);
00801        }
00802 
00803       if(abs_filename)
00804        /* It would be cleaner to provide the real locale name but then we need a way
00805         * to get back the locale code from it's name and from the boards
00806         *
00807         * locales_asset = g_list_append(locales_asset, gc_locale_get_name(list->data));
00808         *
00809         */
00810        locales_asset = g_list_append(locales_asset, list->data);
00811 
00812     }
00813   
00814 
00815   return locales_asset;
00816 }
00817 
00818 /* key = "locale_sound" */
00819 GtkComboBox *gc_board_config_combo_locales_asset(const gchar *label,
00820                                      gchar *init,
00821                                      const gchar *file)
00822 {
00823 
00824   GtkWidget *combobox;
00825   GtkWidget *hbox = gtk_hbox_new (FALSE, 8);
00826   GList *list, *strings;
00827   GtkWidget *label_combo;
00828   gint init_index = 0;
00829 
00830   strings = gc_locale_gets_asset_list(file);
00831 
00832   strings = g_list_prepend( strings, _("Default"));
00833 
00834   if (init)
00835     {
00836       init_index =  g_list_position(strings,
00837                                 g_list_find_custom(strings,
00838                                                  (gconstpointer)init,
00839                                                  (GCompareFunc) my_strcmp));
00840     }
00841 
00842   if (init_index < 0)
00843     init_index=0;
00844   
00845   gtk_widget_show(hbox);
00846   
00847   gtk_box_pack_start (GTK_BOX(main_conf_box),
00848                     hbox,
00849                     FALSE,
00850                     FALSE,
00851                     0);
00852 
00853   /* Label */
00854   label_combo = gtk_label_new ((gchar *)NULL);
00855   gtk_widget_show(label_combo);
00856   gtk_box_pack_start (GTK_BOX(hbox),
00857                     label_combo,
00858                     FALSE,
00859                     FALSE,
00860                     0);
00861 
00862   gtk_label_set_justify (GTK_LABEL(label_combo),
00863                       GTK_JUSTIFY_RIGHT);
00864 
00865   gtk_label_set_markup (GTK_LABEL(label_combo),
00866                         label);
00867 
00868   combobox = gtk_combo_box_new_text();
00869 
00870   gtk_widget_show(combobox);
00871 
00872   gtk_box_pack_start (GTK_BOX(hbox),
00873                     combobox,
00874                     FALSE,
00875                     FALSE,
00876                     0);
00877 
00878 
00879   for (list = strings; list != NULL; list = list->next)
00880     gtk_combo_box_append_text(GTK_COMBO_BOX(combobox),
00881                            list->data);
00882 
00883   if (g_list_length(strings) > COMBOBOX_COL_MAX)
00884     gtk_combo_box_set_wrap_width(GTK_COMBO_BOX(combobox),
00885                              g_list_length(strings) / COMBOBOX_COL_MAX +1 );
00886   
00887   gtk_combo_box_set_active (GTK_COMBO_BOX(combobox),
00888                          init_index);
00889   
00890   g_signal_connect(G_OBJECT(combobox),
00891                  "changed",
00892                  G_CALLBACK(gc_board_config_combo_locales_changed),
00893                  "locale_sound");
00894 
00895   return GTK_COMBO_BOX(combobox);
00896 
00897 }
00898 
00899 /****************************************/
00900 /* TextView                             */
00901 
00902 typedef struct {
00903   gchar *key;
00904   GcomprisTextCallback callback;
00905   GtkLabel *feedback;
00906   GtkTextBuffer *TextBuffer;
00907 } user_param_type;
00908 
00909 static void *
00910 _textview_destroy (GtkButton *button,
00911                  gpointer user_data)
00912 {
00913   g_free(((user_param_type *)user_data)->key);
00914   g_free(user_data);
00915 
00916   return NULL;
00917 }
00918 
00919 
00920 static void *
00921 _textbuffer_changed (GtkTextBuffer *buffer,
00922                    gpointer user_data)
00923 {
00924   gtk_widget_set_sensitive        (GTK_WIDGET(user_data),
00925                                TRUE);
00926 
00927   return NULL;
00928 }
00929 
00930 static void *
00931 _textview_yes (GtkButton *button,
00932               gpointer user_data)
00933 {
00934 
00935   user_param_type *params= (user_param_type *) user_data;
00936 
00937   gchar *key = params->key;
00938   GcomprisTextCallback validate = params->callback;
00939   GtkLabel *label = params->feedback;
00940   GtkTextBuffer *text_buffer = params->TextBuffer;
00941 
00942   GtkTextIter start_iter;
00943   GtkTextIter end_iter;
00944 
00945   gtk_text_buffer_get_start_iter  (text_buffer,
00946                                    &start_iter);
00947 
00948   gtk_text_buffer_get_end_iter  (text_buffer,
00949                              &end_iter);
00950     
00951   /* has this to be freed ? */
00952   gchar *text = gtk_text_buffer_get_slice (text_buffer,
00953                                       &start_iter,
00954                                       &end_iter,
00955                                       TRUE);
00956 
00957   
00958 
00959   gchar *in_memoriam_text = g_strdup (text);
00960   gchar *in_memoriam_key = g_strdup (key);
00961 
00962   if (validate( key, text, label)){
00963     g_hash_table_replace ( hash_conf, (gpointer) in_memoriam_key, (gpointer) in_memoriam_text);
00964     gtk_widget_set_sensitive        (GTK_WIDGET(button),
00965                                  FALSE);
00966   }
00967   else {
00968     g_free (in_memoriam_text);
00969     g_free (in_memoriam_key);
00970   }
00971   g_free(text);
00972 
00973   return NULL;
00974 }
00975 
00976 GtkTextView *
00977 gc_board_config_textview(const gchar *label, 
00978                 gchar *key,
00979                 const gchar*description, 
00980                 gchar *init_text, 
00981                 GcomprisTextCallback validate)
00982 {
00983   GtkWidget*frame =  gtk_frame_new ("GCompris text tool");
00984   gtk_widget_show(frame);
00985 
00986   gtk_box_pack_start (GTK_BOX(main_conf_box),
00987                     frame,
00988                     FALSE,
00989                     FALSE,
00990                     8);
00991   
00992 
00993   
00994   /* Main vbox for all our widegt */
00995   GtkWidget *textVbox = gtk_vbox_new ( FALSE, 8);
00996   gtk_widget_show(textVbox);
00997 
00998   gtk_container_add(GTK_CONTAINER(frame),
00999                   textVbox);
01000   /* Title */
01001   GtkWidget *title = gtk_label_new ((gchar *)NULL);
01002   gtk_widget_show(title);
01003 
01004   gtk_box_pack_start (GTK_BOX(textVbox),
01005                     title,
01006                     FALSE,
01007                     FALSE,
01008                     8);
01009 
01010   gtk_label_set_justify (GTK_LABEL(title),
01011                       GTK_JUSTIFY_CENTER);
01012   
01013   gchar *title_text = g_strdup(label);
01014   gtk_label_set_markup (GTK_LABEL(title),
01015                         (const gchar *)title_text);
01016  
01017   GtkWidget *separator = gtk_hseparator_new ();
01018 
01019   gtk_widget_show(separator);
01020 
01021   gtk_box_pack_start (GTK_BOX(textVbox),
01022                     separator,
01023                     FALSE,
01024                     FALSE,
01025                     0);
01026 
01027   /* Description */
01028   GtkWidget *desc = gtk_label_new ((gchar *)NULL);
01029   gtk_widget_show(desc);
01030 
01031   gtk_box_pack_start (GTK_BOX(textVbox),
01032                     desc,
01033                     FALSE,
01034                     FALSE,
01035                     0);
01036 
01037   //gtk_label_set_justify (GTK_LABEL(title),
01038   //           GTK_JUSTIFY_CENTER);
01039 
01040   gtk_label_set_line_wrap(GTK_LABEL(desc), TRUE);
01041 
01042   gchar *desc_text = g_strdup(description);
01043   gtk_label_set_markup (GTK_LABEL(desc),
01044                         (const gchar *)desc_text);
01045  
01046   GtkWidget *scroll = gtk_scrolled_window_new ( NULL, NULL);
01047 
01048   
01049   gtk_scrolled_window_set_policy  (GTK_SCROLLED_WINDOW(scroll),
01050                                GTK_POLICY_AUTOMATIC,
01051                                GTK_POLICY_AUTOMATIC);
01052 
01053   gtk_widget_set_size_request     (scroll,
01054                                -1,
01055                                100);
01056 
01057   gtk_widget_show( scroll);
01058 
01059   gtk_box_pack_start (GTK_BOX(textVbox),
01060                     scroll,
01061                     FALSE,
01062                     FALSE,
01063                     0);
01064 
01065   /* TextView */
01066   GtkWidget *textView = gtk_text_view_new ();
01067   gtk_widget_show(textView);
01068 
01069   gtk_container_add (GTK_CONTAINER(scroll),
01070                    textView);
01071 
01072   gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (textView), GTK_WRAP_WORD_CHAR);
01073 
01074 
01075   GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (textView));
01076 
01077   gtk_text_buffer_set_text (buffer, g_strdup(init_text), -1);
01078 
01079 
01080   /* hbox for feedback and validation button */
01081   GtkWidget *validationHbox = gtk_vbox_new ( FALSE, 8);
01082   gtk_widget_show(validationHbox);
01083 
01084   gtk_box_pack_start (GTK_BOX(textVbox),
01085                     validationHbox,
01086                     FALSE,
01087                     FALSE,
01088                     0);
01089 
01090   /* Feedback */
01091   GtkWidget *feedback = gtk_label_new ((gchar *)NULL);
01092   gtk_widget_show(feedback);
01093 
01094   gtk_box_pack_start (GTK_BOX(validationHbox),
01095                     feedback,
01096                     FALSE,
01097                     FALSE,
01098                     0);
01099   
01100   gtk_label_set_justify (GTK_LABEL(title),
01101                       GTK_JUSTIFY_FILL);
01102   
01103   gtk_label_set_line_wrap(GTK_LABEL(feedback), TRUE);
01104   
01105   user_param_type *user_param = g_malloc0(sizeof(user_param_type));
01106 
01107   user_param->key = g_strdup(key);
01108   user_param->callback = validate;
01109   user_param->feedback = GTK_LABEL(feedback);
01110   user_param->TextBuffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW(textView));
01111 
01112 
01113   /* vbox for feedback and validation button */
01114   GtkWidget *validationVbox = gtk_hbox_new ( FALSE, 8);
01115   gtk_widget_show(validationVbox);
01116 
01117   gtk_box_pack_end (GTK_BOX(validationHbox),
01118                   validationVbox,
01119                   FALSE,
01120                   FALSE,
01121                   0);
01122 
01123 
01124   /* Validate button */
01125   GtkWidget *button =  gtk_button_new_from_stock (GTK_STOCK_YES);
01126   gtk_widget_show(button);
01127   gtk_box_pack_end (GTK_BOX(validationVbox),
01128                   button,
01129                   FALSE,
01130                   FALSE,
01131                   0);
01132 
01133   g_signal_connect(G_OBJECT(button), 
01134                  "clicked",
01135                  G_CALLBACK(_textview_yes),
01136                  (gpointer) user_param);
01137 
01138 
01139   g_signal_connect(G_OBJECT(button), 
01140                  "destroy",
01141                  G_CALLBACK(_textview_destroy),
01142                  (gpointer) user_param);
01143 
01144   g_signal_connect(G_OBJECT(user_param->TextBuffer), 
01145                  "changed",
01146                  G_CALLBACK(_textbuffer_changed),
01147                  (gpointer) button);
01148 
01149   gtk_widget_set_sensitive (button,
01150                          FALSE);
01151 
01152   return GTK_TEXT_VIEW(textView);
01153 }