gschem

gschem_dialog.c

Go to the documentation of this file.
00001 /* gEDA - GPL Electronic Design Automation
00002  * gschem - gEDA Schematic Capture
00003  * Copyright (C) 1998-2010 Ales Hvezda
00004  * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details)
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00019  */
00020 
00021 #include <config.h>
00022 #include <glib.h>
00023 
00024 #include <glib-object.h>
00025 #include <glib/gstdio.h>
00026 
00027 #include "gschem.h"
00028 #include <gdk/gdkkeysyms.h>
00029 
00030 #ifdef HAVE_LIBDMALLOC
00031 #include <dmalloc.h>
00032 #endif
00033 
00034 
00035 #include "../include/gschem_dialog.h"
00036 
00037 /* Signal marshaller based on generated code from glib-genmarshal */
00038 static void
00039 gschem_marshal_VOID__POINTER_STRING (GClosure     *closure,
00040                                      GValue       *return_value,
00041                                      guint         n_param_values,
00042                                      const GValue *param_values,
00043                                      gpointer      invocation_hint,
00044                                      gpointer      marshal_data)
00045 {
00046   typedef void (*GMarshalFunc_VOID__POINTER_STRING) (gpointer     data1,
00047                                                      gpointer     arg_1,
00048                                                      gpointer     arg_2,
00049                                                      gpointer     data2);
00050   register GMarshalFunc_VOID__POINTER_STRING callback;
00051   register GCClosure *cc = (GCClosure*) closure;
00052   register gpointer data1, data2;
00053 
00054   g_return_if_fail (n_param_values == 3);
00055 
00056   if (G_CCLOSURE_SWAP_DATA (closure)) {
00057     data1 = closure->data;
00058     data2 = g_value_peek_pointer (param_values + 0);
00059   } else {
00060     data1 = g_value_peek_pointer (param_values + 0);
00061     data2 = closure->data;
00062   }
00063   callback = (GMarshalFunc_VOID__POINTER_STRING) (marshal_data ? marshal_data : cc->callback);
00064 
00065   callback (data1,
00066             g_value_get_pointer (param_values + 1),
00067             (gchar*)g_value_get_string (param_values + 2),
00068             data2);
00069 }
00070 /* End section based on generated code from glib-genmashal */
00071 
00072 
00073 enum {
00074   PROP_SETTINGS_NAME = 1,
00075   PROP_GSCHEM_TOPLEVEL
00076 };
00077 
00078 
00079 enum {
00080   GEOMETRY_SAVE,
00081   GEOMETRY_RESTORE,
00082   LAST_SIGNAL
00083 };
00084 
00085 static guint gschem_dialog_signals[ LAST_SIGNAL ] = { 0 };
00086 static GObjectClass *gschem_dialog_parent_class = NULL;
00087 
00088 static GKeyFile *dialog_geometry = NULL;
00089 
00090 #define DIALOG_GEOMETRY_STORE "gschem-dialog-geometry"
00091 
00092 
00100 static void save_geometry_to_file(gpointer user_data)
00101 {
00102   gchar *data, *file;
00103 
00104   g_assert( dialog_geometry != NULL );
00105 
00106   data = g_key_file_to_data(dialog_geometry, NULL, NULL);
00107   file = g_build_filename(s_path_user_config (), DIALOG_GEOMETRY_STORE,
00108         NULL);
00109   g_file_set_contents(file, data, -1, NULL);
00110   g_free(data);
00111   g_free(file);
00112 }
00113 
00114 
00124 static void geometry_save (GschemDialog *dialog, GKeyFile *key_file, gchar* group_name)
00125 {
00126   gint x, y, width, height;
00127 
00128   gtk_window_get_position (GTK_WINDOW (dialog), &x, &y);
00129   gtk_window_get_size (GTK_WINDOW (dialog), &width, &height);
00130 
00131   g_key_file_set_integer (key_file, group_name, "x", x);
00132   g_key_file_set_integer (key_file, group_name, "y", y);
00133   g_key_file_set_integer (key_file, group_name, "width",  width );
00134   g_key_file_set_integer (key_file, group_name, "height", height);
00135 }
00136 
00137 
00147 static void geometry_restore (GschemDialog *dialog, GKeyFile *key_file, gchar* group_name)
00148 {
00149   gint x, y, width, height;
00150 
00151   x      = g_key_file_get_integer (key_file, group_name, "x", NULL);
00152   y      = g_key_file_get_integer (key_file, group_name, "y", NULL);
00153   width  = g_key_file_get_integer (key_file, group_name, "width",  NULL);
00154   height = g_key_file_get_integer (key_file, group_name, "height", NULL);
00155 
00156   gtk_window_move (GTK_WINDOW (dialog), x, y);
00157   gtk_window_resize (GTK_WINDOW (dialog), width, height);
00158 }
00159 
00160 
00168 static void setup_keyfile ()
00169 {
00170   if (dialog_geometry != NULL)
00171     return;
00172 
00173   gchar *file = g_build_filename (s_path_user_config (),
00174                                   DIALOG_GEOMETRY_STORE, NULL);
00175 
00176   dialog_geometry = g_key_file_new();
00177 
00178   /* Remember to save data on program exit */
00179   gschem_atexit(save_geometry_to_file, NULL);
00180 
00181   if (!g_file_test (file, G_FILE_TEST_EXISTS)) {
00182     g_mkdir (s_path_user_config (), S_IRWXU | S_IRWXG);
00183 
00184     g_file_set_contents (file, "", -1, NULL);
00185   }
00186 
00187   if (!g_key_file_load_from_file (dialog_geometry, file, G_KEY_FILE_NONE, NULL)) {
00188     /* error opening key file, create an empty one and try again */
00189     g_file_set_contents (file, "", -1, NULL);
00190     if ( !g_key_file_load_from_file (dialog_geometry, file, G_KEY_FILE_NONE, NULL)) {
00191        g_free (file);
00192        return;
00193     }
00194   }
00195   g_free (file);
00196 }
00197 
00198 
00207 static void show_handler (GtkWidget *widget)
00208 {
00209   gchar *group_name;
00210   GschemDialog *dialog = GSCHEM_DIALOG( widget );
00211 
00212   group_name = dialog->settings_name;
00213   if (group_name != NULL) {
00214 
00215     setup_keyfile ();
00216     g_assert( dialog_geometry != NULL );
00217     if (g_key_file_has_group (dialog_geometry, group_name)) {
00218       g_signal_emit (dialog, gschem_dialog_signals[ GEOMETRY_RESTORE ], 0,
00219                      dialog_geometry, group_name);
00220     }
00221   }
00222 
00223   /* Let GTK show the window */
00224   GTK_WIDGET_CLASS (gschem_dialog_parent_class)->show (widget);
00225 }
00226 
00227 
00238 static void unmap_handler (GtkWidget *widget)
00239 {
00240   gchar *group_name;
00241   GschemDialog *dialog = GSCHEM_DIALOG (widget);
00242 
00243   group_name = dialog->settings_name;
00244   if (group_name != NULL) {
00245 
00246     g_assert( dialog_geometry != NULL );
00247     g_signal_emit (dialog, gschem_dialog_signals[ GEOMETRY_SAVE ], 0,
00248                    dialog_geometry, group_name);
00249   }
00250 
00251   /* Let GTK unmap the window */
00252   GTK_WIDGET_CLASS (gschem_dialog_parent_class)->unmap (widget);
00253 }
00254 
00255 
00264 static void gschem_dialog_finalize (GObject *object)
00265 {
00266   GschemDialog *dialog = GSCHEM_DIALOG (object);
00267 
00268   g_free (dialog->settings_name);
00269 
00270   G_OBJECT_CLASS (gschem_dialog_parent_class)->finalize (object);
00271 }
00272 
00273 
00286 static void gschem_dialog_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
00287 {
00288   GschemDialog *dialog = GSCHEM_DIALOG (object);
00289 
00290   switch(property_id) {
00291     case PROP_SETTINGS_NAME:
00292       g_free (dialog->settings_name);
00293       dialog->settings_name = g_strdup (g_value_get_string (value));
00294       break;
00295     case PROP_GSCHEM_TOPLEVEL:
00296       dialog->w_current = (GSCHEM_TOPLEVEL*)g_value_get_pointer (value);
00297       break;
00298     default:
00299       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
00300   }
00301 
00302 }
00303 
00304 
00317 static void gschem_dialog_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
00318 {
00319   GschemDialog *dialog = GSCHEM_DIALOG (object);
00320 
00321   switch(property_id) {
00322       case PROP_SETTINGS_NAME:
00323         g_value_set_string (value, dialog->settings_name);
00324         break;
00325       case PROP_GSCHEM_TOPLEVEL:
00326         g_value_set_pointer (value, (gpointer)dialog->w_current);
00327         break;
00328       default:
00329         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
00330   }
00331 
00332 }
00333 
00334 
00343 static void gschem_dialog_class_init (GschemDialogClass *klass)
00344 {
00345   GObjectClass     *gobject_class = G_OBJECT_CLASS (klass);
00346   GtkWidgetClass *gtkwidget_class = GTK_WIDGET_CLASS (klass);
00347 
00348   klass->geometry_save         = geometry_save;
00349   klass->geometry_restore      = geometry_restore;
00350 
00351   gtkwidget_class->show        = show_handler;
00352   gtkwidget_class->unmap       = unmap_handler;
00353 
00354   gobject_class->finalize      = gschem_dialog_finalize;
00355   gobject_class->set_property  = gschem_dialog_set_property;
00356   gobject_class->get_property  = gschem_dialog_get_property;
00357 
00358   gschem_dialog_parent_class = g_type_class_peek_parent (klass);
00359 
00360   gschem_dialog_signals[ GEOMETRY_SAVE ] =
00361     g_signal_new ("geometry-save",
00362                   G_OBJECT_CLASS_TYPE( gobject_class ),
00363                   G_SIGNAL_RUN_FIRST,     /*signal_flags */
00364                   G_STRUCT_OFFSET( GschemDialogClass, geometry_save ),
00365                   NULL, /* accumulator */
00366                   NULL, /* accu_data */
00367                   gschem_marshal_VOID__POINTER_STRING,
00368                   G_TYPE_NONE,
00369                   2,    /* n_params */
00370                   G_TYPE_POINTER,
00371                   G_TYPE_STRING
00372                  );
00373 
00374   gschem_dialog_signals[ GEOMETRY_RESTORE ] =
00375     g_signal_new ("geometry-restore",
00376                   G_OBJECT_CLASS_TYPE( gobject_class ),
00377                   G_SIGNAL_RUN_FIRST,     /*signal_flags */
00378                   G_STRUCT_OFFSET( GschemDialogClass, geometry_restore ),
00379                   NULL, /* accumulator */
00380                   NULL, /* accu_data */
00381                   gschem_marshal_VOID__POINTER_STRING,
00382                   G_TYPE_NONE,
00383                   2,    /* n_params */
00384                   G_TYPE_POINTER,
00385                   G_TYPE_STRING
00386                  );
00387 
00388   g_object_class_install_property (
00389     gobject_class, PROP_SETTINGS_NAME,
00390     g_param_spec_string ("settings-name",
00391                          "",
00392                          "",
00393                          NULL,
00394                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
00395   g_object_class_install_property (
00396     gobject_class, PROP_GSCHEM_TOPLEVEL,
00397     g_param_spec_pointer ("gschem-toplevel",
00398                           "",
00399                           "",
00400                           G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));
00401 }
00402 
00403 
00413 GType gschem_dialog_get_type ()
00414 {
00415   static GType gschem_dialog_type = 0;
00416 
00417   if (!gschem_dialog_type) {
00418     static const GTypeInfo gschem_dialog_info = {
00419       sizeof(GschemDialogClass),
00420       NULL, /* base_init */
00421       NULL, /* base_finalize */
00422       (GClassInitFunc) gschem_dialog_class_init,
00423       NULL, /* class_finalize */
00424       NULL, /* class_data */
00425       sizeof(GschemDialog),
00426       0,    /* n_preallocs */
00427       NULL, /* instance_init */
00428     };
00429 
00430     gschem_dialog_type = g_type_register_static (GTK_TYPE_DIALOG,
00431                                                  "GschemDialog",
00432                                                  &gschem_dialog_info, 0);
00433   }
00434 
00435   return gschem_dialog_type;
00436 }
00437 
00438 
00449 static void gschem_dialog_add_buttons_valist (GtkDialog      *dialog,
00450                                               const gchar    *first_button_text,
00451                                               va_list         args)
00452 {
00453   const gchar* text;
00454   gint response_id;
00455 
00456   g_return_if_fail (GTK_IS_DIALOG (dialog));
00457 
00458   if (first_button_text == NULL)
00459     return;
00460 
00461   text = first_button_text;
00462   response_id = va_arg (args, gint);
00463 
00464   while (text != NULL)
00465     {
00466       gtk_dialog_add_button (dialog, text, response_id);
00467 
00468       text = va_arg (args, gchar*);
00469       if (text == NULL)
00470         break;
00471       response_id = va_arg (args, int);
00472     }
00473 }
00474 
00475 
00490 static GtkWidget* gschem_dialog_new_empty (const gchar     *title,
00491                                            GtkWindow       *parent,
00492                                            GtkDialogFlags   flags,
00493                                            const gchar *settings_name,
00494                                            GSCHEM_TOPLEVEL *w_current)
00495 {
00496   GschemDialog *dialog;
00497 
00498   dialog = g_object_new (GSCHEM_TYPE_DIALOG,
00499                          "settings-name", settings_name,
00500                          "gschem-toplevel", w_current,
00501                          NULL);
00502 
00503   if (title)
00504     gtk_window_set_title (GTK_WINDOW (dialog), title);
00505 
00506   if (parent)
00507     gtk_window_set_transient_for (GTK_WINDOW (dialog), parent);
00508 
00509   if (flags & GTK_DIALOG_MODAL)
00510     gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
00511 
00512   if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
00513     gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
00514 
00515   if (flags & GTK_DIALOG_NO_SEPARATOR)
00516     gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
00517 
00518   return GTK_WIDGET (dialog);
00519 }
00520 
00521 
00539 GtkWidget* gschem_dialog_new_with_buttons (const gchar *title, GtkWindow *parent, GtkDialogFlags flags,
00540                                            const gchar *settings_name, GSCHEM_TOPLEVEL *w_current,
00541                                            const gchar *first_button_text, ...)
00542 {
00543   GschemDialog *dialog;
00544   va_list args;
00545 
00546   dialog = GSCHEM_DIALOG (gschem_dialog_new_empty (title, parent, flags, settings_name, w_current));
00547 
00548   va_start (args, first_button_text);
00549 
00550   gschem_dialog_add_buttons_valist (GTK_DIALOG (dialog),
00551                                     first_button_text,
00552                                     args);
00553 
00554   va_end (args);
00555 
00556   return GTK_WIDGET (dialog);
00557 }
00558 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines