gschem
|
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 }