gschem

x_menus.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 #include "config.h"
00021 #include <missing.h>
00022 
00023 #ifdef HAVE_STRING_H
00024 #include <string.h>
00025 #endif
00026 
00027 
00028 #include "gschem.h"
00029 
00030 #include <glib/gstdio.h>
00031 
00032 #ifdef HAVE_LIBDMALLOC
00033 #include <dmalloc.h>
00034 #endif
00035 
00036 static GtkItemFactoryEntry popup_items[] = {
00037   { N_("/Add Net"),           NULL, i_callback_add_net,           0, NULL},
00038   { N_("/Add Attribute..."),  NULL, i_callback_add_attribute,     0, NULL},
00039   { N_("/Add Component..."),  NULL, i_callback_add_component,     0, NULL},
00040   { N_("/Add Bus"),           NULL, i_callback_add_bus,           0, NULL},
00041   { N_("/Add Text"),          NULL, i_callback_add_text,          0, NULL},
00042   { "/sep1", NULL, NULL, 0, "<Separator>"},
00043   { N_("/Zoom In"),       NULL, i_callback_view_zoom_in,      0, NULL},
00044   { N_("/Zoom Out"),      NULL, i_callback_view_zoom_out,     0, NULL},
00045   { N_("/Zoom Box"),      NULL, i_callback_view_zoom_box,     0, NULL},
00046   { N_("/Zoom Extents"),  NULL, i_callback_view_zoom_extents, 0, NULL},
00047   { "/sep1", NULL, NULL, 0, "<Separator>"},
00048   { N_("/Select"),    NULL, i_callback_edit_select,       0, NULL},
00049   { N_("/Edit..."),       NULL, i_callback_edit_edit,         0, NULL},
00050   { N_("/Edit pin type..."),      NULL, i_callback_edit_pin_type,         0, NULL},
00051   { N_("/Copy"),          NULL, i_callback_edit_copy,         0, NULL},
00052   { N_("/Move"),          NULL, i_callback_edit_move,         0, NULL},
00053   { N_("/Delete"),        NULL, i_callback_edit_delete,       0, NULL},
00054   /* Menu items for hierarchy added by SDB 1.9.2005.  */
00055   {"/sep1", NULL, NULL, 0, "<Separator>"},
00056   {N_("/Down Schematic"), NULL, i_callback_hierarchy_down_schematic, 0, NULL},
00057   {N_("/Down Symbol"),    NULL, i_callback_hierarchy_down_symbol,    0, NULL},
00058   {N_("/Up"),             NULL, i_callback_hierarchy_up,             0, NULL},
00059 };  
00060 
00061 int npopup_items = sizeof(popup_items) / sizeof(popup_items[0]);
00062 
00068 static void g_menu_execute(GtkAction *action, gpointer user_data)
00069 {
00070   gchar *guile_string = NULL;
00071   const gchar *func = gtk_action_get_name (action);
00072   GSCHEM_TOPLEVEL *w_current = (GSCHEM_TOPLEVEL *) user_data;
00073 
00074   guile_string = g_strdup_printf("(%s)", func);
00075 #if DEBUG
00076   printf("%s\n", guile_string);
00077 #endif
00078   scm_dynwind_begin (0);
00079   scm_dynwind_unwind_handler (g_free, guile_string, SCM_F_WIND_EXPLICITLY);
00080   g_dynwind_window (w_current);
00081   g_scm_c_eval_string_protected (guile_string);
00082   scm_dynwind_end ();
00083 }
00084 
00090 GtkWidget *
00091 get_main_menu(GSCHEM_TOPLEVEL *w_current)
00092 {
00093   char *buf;
00094   GschemAction *action;
00095   GtkWidget *menu_item;
00096   GtkWidget *root_menu;
00097   GtkWidget *menu_bar;
00098   GtkWidget *menu;
00099   int scm_items_len;
00100   SCM scm_items;
00101   SCM scm_item;
00102   SCM scm_item_name;
00103   SCM scm_item_func;
00104   SCM scm_item_hotkey_func;
00105   SCM scm_item_stock;
00106   SCM scm_index;
00107   SCM scm_keys;
00108   char *menu_name;
00109   char *action_name;
00110   char **raw_menu_name = g_malloc (sizeof(char *));
00111   char *menu_item_name;
00112   char *raw_menu_item_name;
00113   char *menu_item_hotkey_func;
00114   char *menu_item_stock;
00115   char *menu_item_keys;
00116   int i, j;
00117 
00118   menu_bar = gtk_menu_bar_new ();
00119 
00120   scm_dynwind_begin (0);
00121   g_dynwind_window (w_current);
00126   for (i = 0 ; i < s_menu_return_num(); i++) {
00127     
00128     scm_items = s_menu_return_entry(i, raw_menu_name);   
00129     if (*raw_menu_name == NULL) {
00130       fprintf(stderr, "Oops.. got a NULL menu name in get_main_menu()\n");
00131       exit(-1);
00132     }
00133 
00134     menu = gtk_menu_new();
00135 
00136     menu_item = gtk_tearoff_menu_item_new ();
00137     gtk_menu_append(GTK_MENU(menu), menu_item);
00138     gtk_widget_show(menu_item);
00139 
00140     scm_items_len = (int) scm_ilength (scm_items);
00141     for (j = 0 ; j < scm_items_len; j++) {
00142 
00143       scm_index = scm_from_int (j);
00144       scm_item = scm_list_ref (scm_items, scm_index);
00145       scm_item_name = SCM_CAR (scm_item);
00146       scm_item_func = SCM_CADR (scm_item);
00147       scm_item_hotkey_func = SCM_CADDR (scm_item);
00148       scm_item_stock = scm_is_pair (SCM_CDDDR (scm_item)) ?
00149                          SCM_CADDDR (scm_item) : SCM_BOOL_F;
00150       SCM_ASSERT(scm_is_string(scm_item_name), scm_item_name, SCM_ARGn, "get_main_menu item_name");
00151       SCM_ASSERT(scm_is_symbol (scm_item_func) ||
00152                     scm_is_false (scm_item_func),
00153                  scm_item_func, SCM_ARGn, "get_main_menu item_func");
00154       SCM_ASSERT (scm_is_symbol (scm_item_hotkey_func) ||
00155                     scm_is_false (scm_item_hotkey_func),
00156                   scm_item_hotkey_func, SCM_ARGn, "get_main_menu hotkey_func");
00157       SCM_ASSERT (scm_is_string (scm_item_stock) ||
00158                     scm_is_false (scm_item_stock),
00159                   scm_item_stock, SCM_ARGn, "get_main_menu stock");
00160 
00161       raw_menu_item_name = scm_to_utf8_string(scm_item_name);
00162       scm_dynwind_begin(0);
00163       scm_dynwind_free(raw_menu_item_name);
00164 
00165       menu_item_name = (char *) gettext(raw_menu_item_name);
00166 
00167       if (strcmp(menu_item_name, "SEPARATOR") == 0) {
00168         menu_item = gtk_menu_item_new();
00169         gtk_menu_append(GTK_MENU(menu), menu_item);
00170       } else {
00171 
00172         if (scm_is_false (scm_item_hotkey_func)) {
00173           menu_item_hotkey_func = NULL;
00174         } else {
00175           menu_item_hotkey_func = scm_to_utf8_string (scm_symbol_to_string (scm_item_hotkey_func));
00176           scm_dynwind_free (menu_item_hotkey_func);
00177         }
00178 
00179         if (menu_item_hotkey_func != NULL) {
00180           SCM s_expr =
00181             scm_list_2 (scm_from_utf8_symbol ("find-key"),
00182                         scm_list_2 (scm_from_utf8_symbol ("quote"),
00183                                     scm_from_utf8_symbol (menu_item_hotkey_func)));
00184 
00185           scm_keys = g_scm_eval_protected (s_expr, scm_interaction_environment ());
00186 
00187           if (scm_is_false (scm_keys)) {
00188             menu_item_keys = "";
00189           } else {
00190             menu_item_keys = scm_to_utf8_string (scm_keys);
00191             scm_dynwind_free(menu_item_keys);
00192           }
00193 
00194         } else {
00195           menu_item_keys = "";
00196         }
00197 
00198         if(scm_is_false (scm_item_func)) {
00199           menu_item = gtk_menu_item_new_with_mnemonic(menu_item_name);
00200         } else {
00201           if (scm_is_false (scm_item_stock))
00202             menu_item_stock = NULL;
00203           else
00204             menu_item_stock = scm_to_utf8_string (scm_item_stock);
00205 
00206           action_name = scm_to_utf8_string (scm_symbol_to_string (scm_item_func));
00207           action = gschem_action_new (action_name,  /* Action name */
00208                                       menu_item_name,  /* Text */
00209                                       menu_item_name,  /* Tooltip */
00210                                       menu_item_stock, /* Icon stock ID */
00211                                       menu_item_keys); /* Accelerator string */
00212           free(action_name);
00213           free(menu_item_stock);
00214 
00215           menu_item = gtk_action_create_menu_item (GTK_ACTION (action));
00216           g_signal_connect (G_OBJECT(action), "activate",
00217                             G_CALLBACK(g_menu_execute),
00218                             w_current);
00219         }
00220 
00221         gtk_menu_append (GTK_MENU (menu), menu_item);
00222       }
00223 
00224       gtk_widget_show (menu_item);
00225 
00226       /* add a handle to the menu_bar object to get access to widget objects */
00227       /* This string should NOT be internationalized */
00228       buf = g_strdup_printf("%s/%s", *raw_menu_name, raw_menu_item_name);
00229       gtk_object_set_data(GTK_OBJECT(menu_bar), buf, menu_item);
00230       g_free(buf);
00231 
00232       scm_dynwind_end();
00233     }
00234     
00235     menu_name = (char *) gettext(*raw_menu_name);
00236     root_menu = gtk_menu_item_new_with_mnemonic (menu_name);
00237     /* do not free *raw_menu_name */
00238 
00239     /* no longer right justify the help menu since that has gone out of style */
00240 
00241     gtk_widget_show (root_menu);
00242     gtk_menu_item_set_submenu (GTK_MENU_ITEM (root_menu), menu);
00243     gtk_menu_bar_append (GTK_MENU_BAR (menu_bar), root_menu);
00244   }
00245   scm_dynwind_end ();
00246 
00247   g_free(raw_menu_name);
00248   return menu_bar;
00249 }
00250 
00256 static gchar* gettext_fn(const gchar *path,
00257              gpointer func_data ATTRIBUTE_UNUSED)
00258 {
00263   return (gchar *) gettext(path);
00264 }
00265 
00266 GtkWidget *get_main_popup(GSCHEM_TOPLEVEL *w_current)
00267 {
00268   static GtkItemFactory *item_factory;
00269   GtkAccelGroup *accel_group;
00270   GtkWidget *menu;
00271 
00272   accel_group = gtk_accel_group_new();
00273 
00274   /* This function initializes the item factory.
00275      Param 1: The type of menu - can be GTK_TYPE_MENU_BAR, GTK_TYPE_MENU, or GTK_TYPE_OPTION_MENU.
00276      Param 2: The path of the menu.
00277      Param 3: A pointer to a gtk_accel_group.  The item factory sets up
00278      the accelerator table while generating menus.
00279   */
00280   item_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<popup>",
00281                                       accel_group);
00282   gtk_item_factory_set_translate_func (item_factory,
00283                                        gettext_fn,
00284                                        NULL, NULL);
00285   /* This function creates the pop-up menu itself & attaches it to the
00286      GtkItemFactory. Pass the item factory,
00287      the number of items in the array, the array itself, and any
00288      callback data for the the menu items. Note that npopup_items is 
00289      a static var declared in this file above; popup_items is also a
00290      static var declared above.
00291   */
00292   gtk_item_factory_create_items(item_factory, npopup_items, popup_items, w_current);
00293 
00294   /* Finally, return the actual menu created by the item factory. */
00295   menu = (GtkWidget *) gtk_item_factory_get_widget(item_factory, "<popup>");
00296   return (menu);
00297 
00298 }
00299 
00307 gint do_popup (GSCHEM_TOPLEVEL *w_current, GdkEventButton *event)
00308 {
00309   GtkWidget *menu;   /* =NULL; */ /* was static */
00310 
00311   menu = NULL;  /* Why do I need to do this? */
00312   if (!menu)
00313     menu = (GtkWidget *) w_current->popup_menu;
00314 
00315   if (menu == NULL) {
00316     printf("null menu\n");
00317   }
00318 
00319   gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL,
00320                   event->button, event->time);
00321 
00322   return FALSE;
00323 }
00324 
00330 void x_menus_sensitivity (GSCHEM_TOPLEVEL *w_current, const char *buf, int flag)
00331 {
00332   GtkWidget* item=NULL;
00333   
00334   if (!buf) {
00335     return;
00336   }
00337 
00338   if (!w_current->menubar) {
00339     return;
00340   }
00341   
00342   item = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar), buf);
00343 
00344   if (item) {
00345     gtk_widget_set_sensitive(GTK_WIDGET(item), flag);
00346     /* free(item); */ /* Why doesn't this need to be freed?  */
00347   } else {
00348     s_log_message(_("Tried to set the sensitivity on non-existent menu item '%s'\n"), buf); 
00349   }
00350  
00351 }
00352 
00362 void x_menus_popup_sensitivity (GSCHEM_TOPLEVEL *w_current, const char *buf, int flag)
00363 {
00364   GtkWidget *menu_item;
00365   GtkItemFactory *menu_item_factory;
00366   
00367   if (!buf) {
00368     return;
00369   }
00370 
00371   if (!w_current->popup_menu) {
00372     s_log_message(_("Popup_menu_item_factory doesn't exist!\n")); 
00373     return;
00374   }
00375 
00376   /* 
00377    * first get entire item factory from popup, then get the individual 
00378    * menu item indexed by buf.
00379    */
00380   menu_item_factory = (GtkItemFactory *)gtk_item_factory_from_widget(w_current->popup_menu);  
00381   menu_item = (GtkWidget *) gtk_item_factory_get_widget(menu_item_factory, buf);
00382   if (menu_item) {
00383     gtk_widget_set_sensitive(GTK_WIDGET(menu_item), flag);
00384   } else {
00385     s_log_message(_("Tried to set the sensitivity on a non-existent popup menu_item\n")); 
00386   }
00387 }
00388 
00389 #define MAX_RECENT_FILES 10
00390 
00394 void
00395 recent_chooser_item_activated (GtkRecentChooser *chooser, GSCHEM_TOPLEVEL *w_current)
00396 {
00397   PAGE *page;
00398   gchar *uri;
00399   gchar *filename;
00400 
00401   uri = gtk_recent_chooser_get_current_uri (chooser);
00402   filename = g_filename_from_uri(uri, NULL, NULL);
00403   gtk_recent_manager_add_item(recent_manager, uri);
00404   page = x_window_open_page(w_current, (char *)filename);
00405   x_window_set_current_page(w_current, page);
00406 
00407   g_free(uri);
00408   g_free(filename);
00409 }
00410 
00416 void x_menu_attach_recent_files_submenu(GSCHEM_TOPLEVEL *w_current)
00417 {
00418   GtkWidget* menuitem_to_append_to = NULL;
00419   GtkRecentFilter *recent_filter;
00420   GtkWidget *menuitem_file_recent_items;
00421   recent_manager = gtk_recent_manager_get_default();
00422 
00423   menuitem_file_recent_items = gtk_recent_chooser_menu_new_for_manager(recent_manager);
00424 
00425   /* Show only schematic- and symbol-files (*.sch and *.sym) in list */
00426   recent_filter = gtk_recent_filter_new();
00427   gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-schematic");
00428   gtk_recent_filter_add_mime_type(recent_filter, "application/x-geda-symbol");
00429   gtk_recent_filter_add_pattern(recent_filter, "*.sch");
00430   gtk_recent_filter_add_pattern(recent_filter, "*.sym");
00431   gtk_recent_chooser_add_filter(GTK_RECENT_CHOOSER(menuitem_file_recent_items), recent_filter);
00432 
00433   gtk_recent_chooser_set_show_tips(GTK_RECENT_CHOOSER(menuitem_file_recent_items), TRUE);
00434   gtk_recent_chooser_set_sort_type(GTK_RECENT_CHOOSER(menuitem_file_recent_items),
00435                                    GTK_RECENT_SORT_MRU);
00436   gtk_recent_chooser_set_limit(GTK_RECENT_CHOOSER(menuitem_file_recent_items), MAX_RECENT_FILES);
00437   gtk_recent_chooser_set_local_only(GTK_RECENT_CHOOSER(menuitem_file_recent_items), FALSE);
00438   gtk_recent_chooser_menu_set_show_numbers(GTK_RECENT_CHOOSER_MENU(menuitem_file_recent_items), TRUE);
00439   g_signal_connect(GTK_OBJECT(menuitem_file_recent_items), "item-activated",
00440                    G_CALLBACK(recent_chooser_item_activated), w_current);
00441 
00442   menuitem_to_append_to = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(w_current->menubar), "_File/Open Recen_t");
00443   if(menuitem_to_append_to == NULL)
00444     return;
00445   gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem_to_append_to), menuitem_file_recent_items);
00446 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines