gschem

x_window.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 #include <stdio.h>
00024 
00025 #include "gschem.h"
00026 
00027 #ifdef HAVE_LIBDMALLOC
00028 #include <dmalloc.h>
00029 #endif
00030 
00031 #define GSCHEM_THEME_ICON_NAME "geda-gschem"
00032 
00038 void x_window_setup (GSCHEM_TOPLEVEL *w_current)
00039 {
00040   TOPLEVEL *toplevel = w_current->toplevel;
00041 
00042   /* immediately setup user params */
00043   i_vars_set(w_current);
00044 
00045   /* Initialize the autosave callback */
00046   s_page_autosave_init(toplevel);
00047 
00048   /* Initialize the clipboard callback */
00049   x_clipboard_init (w_current);
00050 
00051   /* x_window_setup_world() - BEGIN */
00052   toplevel->init_left = -45;
00053   toplevel->init_top  = -45;
00054   /* init_right and _bottom are set before this function is called */
00055 
00056   toplevel->width  = default_width;
00057   toplevel->height = default_height;
00058 
00059   w_current->win_width  = toplevel->width;
00060   w_current->win_height = toplevel->height;
00061   /* x_window_setup_world() - END */
00062 
00063   /* Add to the list of windows */
00064   global_window_list = g_list_append (global_window_list, w_current);
00065 
00066   /* X related stuff */
00067   x_window_create_main (w_current);
00068 
00069   x_menu_attach_recent_files_submenu(w_current);
00070 }
00071 
00077 void x_window_setup_gc(GSCHEM_TOPLEVEL *w_current)
00078 {
00079   w_current->gc = gdk_gc_new(w_current->window);
00080 
00081   if (w_current->gc == NULL) {
00082     fprintf(stderr, _("Couldn't allocate gc\n"));
00083     exit(-1);
00084   }
00085 }
00086 
00092 void x_window_free_gc(GSCHEM_TOPLEVEL *w_current)
00093 {
00094   gdk_gc_unref(w_current->gc);
00095 }
00096 
00102 void x_window_create_drawing(GtkWidget *drawbox, GSCHEM_TOPLEVEL *w_current)
00103 {
00104   /* drawing next */
00105   w_current->drawing_area = gtk_drawing_area_new ();
00106   /* Set the size here.  Be sure that it has an aspect ratio of 1.333
00107    * We could calculate this based on root window size, but for now
00108    * lets just set it to:
00109    * Width = root_width*3/4   Height = Width/1.3333333333
00110    * 1.3333333 is the desired aspect ratio!
00111    */
00112 
00113   gtk_drawing_area_size (GTK_DRAWING_AREA (w_current->drawing_area),
00114                          w_current->win_width,
00115                          w_current->win_height);
00116 
00117   gtk_box_pack_start (GTK_BOX (drawbox), w_current->drawing_area,
00118                       TRUE, TRUE, 0);
00119   GTK_WIDGET_SET_FLAGS (w_current->drawing_area, GTK_CAN_FOCUS );
00120   gtk_widget_grab_focus (w_current->drawing_area);
00121   gtk_widget_show (w_current->drawing_area);
00122 
00123 }
00124 
00130 void x_window_setup_draw_events(GSCHEM_TOPLEVEL *w_current)
00131 {
00132   struct event_reg_t {
00133     gchar *detailed_signal;
00134     GCallback c_handler;
00135   };
00136 
00137   struct event_reg_t drawing_area_events[] = {
00138     { "expose_event",         G_CALLBACK(x_event_expose)          },
00139     { "button_press_event",   G_CALLBACK(x_event_button_pressed)  },
00140     { "button_release_event", G_CALLBACK(x_event_button_released) },
00141     { "motion_notify_event",  G_CALLBACK(x_event_motion)          },
00142     { "configure_event",      G_CALLBACK(x_event_configure)       },
00143     { "key_press_event",      G_CALLBACK(x_event_key)             },
00144     { "key_release_event",    G_CALLBACK(x_event_key)             },
00145     { NULL,                   NULL                                } };
00146   struct event_reg_t main_window_events[] = {
00147     { "enter_notify_event",   G_CALLBACK(x_event_enter)           },
00148     { "scroll_event",         G_CALLBACK(x_event_scroll)          },
00149     { NULL,                   NULL                                } };
00150   struct event_reg_t *tmp;
00151 
00152   /* is the configure event type missing here? hack */
00153   gtk_widget_set_events (w_current->drawing_area,
00154                          GDK_EXPOSURE_MASK |
00155                          GDK_POINTER_MOTION_MASK |
00156                          GDK_BUTTON_PRESS_MASK   |
00157                          GDK_ENTER_NOTIFY_MASK |
00158                          GDK_KEY_PRESS_MASK |
00159                          GDK_BUTTON_RELEASE_MASK);
00160 
00161   for (tmp = drawing_area_events; tmp->detailed_signal != NULL; tmp++) {
00162     g_signal_connect (w_current->drawing_area,
00163                       tmp->detailed_signal,
00164                       tmp->c_handler,
00165                       w_current);
00166   }
00167 
00168   for (tmp = main_window_events; tmp->detailed_signal != NULL; tmp++) {
00169     g_signal_connect (w_current->main_window,
00170                       tmp->detailed_signal,
00171                       tmp->c_handler,
00172                       w_current);
00173   }           
00174 }
00175 
00176 
00186 static GtkWidget *x_window_stock_pixmap(const char *stock, GSCHEM_TOPLEVEL *w_current)
00187 {
00188   GtkWidget *wpixmap = NULL;
00189   GdkPixmap *pixmap;
00190   GdkBitmap *mask;
00191   GtkStockItem item;
00192 
00193   GdkWindow *window=w_current->main_window->window;
00194   GdkColor *background=&w_current->main_window->style->bg[GTK_STATE_NORMAL];
00195 
00196   gchar *filename=g_strconcat(w_current->toplevel->bitmap_directory,
00197                               G_DIR_SEPARATOR_S, 
00198                               "gschem-", stock, ".xpm", NULL);
00199 
00200   gchar *stockid=g_strconcat("gtk-", stock, NULL);
00201 
00202   /* First check if GTK knows this stock icon */
00203   if(gtk_stock_lookup(stockid, &item)) {
00204     wpixmap = gtk_image_new_from_stock(stockid, 
00205                                        GTK_ICON_SIZE_SMALL_TOOLBAR);
00206   } else {
00207     /* Fallback to the original custom icon */
00208     pixmap = gdk_pixmap_create_from_xpm (window, &mask, 
00209                                          background, filename);
00210     if (pixmap != NULL) {
00211       wpixmap = gtk_image_new_from_pixmap (pixmap, mask);
00212     } else {
00213      s_log_message("Could not find image at file: %s.\n", filename);
00214      wpixmap = gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE , 
00215                     GTK_ICON_SIZE_SMALL_TOOLBAR);
00216     }
00217   }
00218 
00219   g_free(filename);
00220   g_free(stockid);
00221 
00222   return wpixmap;
00223 }
00224 
00225 static void x_window_invoke_macro(GtkEntry *entry, void *userdata)
00226 {
00227   GSCHEM_TOPLEVEL *w_current = userdata;
00228   SCM interpreter;
00229 
00230   interpreter = scm_list_2(scm_from_utf8_symbol("invoke-macro"),
00231                scm_from_utf8_string(gtk_entry_get_text(entry)));
00232 
00233   scm_dynwind_begin (0);
00234   g_dynwind_window (w_current);
00235   g_scm_eval_protected(interpreter, SCM_UNDEFINED);
00236   scm_dynwind_end ();
00237 
00238   gtk_widget_hide(w_current->macro_box);
00239   gtk_widget_grab_focus(w_current->drawing_area);
00240 }
00241 
00247 void x_window_create_main(GSCHEM_TOPLEVEL *w_current)
00248 {
00249   TOPLEVEL *toplevel = w_current->toplevel;
00250 
00251   GtkWidget *label=NULL;
00252   GtkWidget *main_box=NULL;
00253   GtkWidget *menubar=NULL;
00254   GtkWidget *drawbox=NULL;
00255   GtkWidget *bottom_box=NULL;
00256   GtkWidget *toolbar=NULL;
00257   GtkWidget *handlebox=NULL;
00258 
00259   /* used to signify that the window isn't mapped yet */
00260   w_current->window = NULL; 
00261 
00262   w_current->main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00263 
00264   gtk_widget_set_name (w_current->main_window, "gschem");
00265   gtk_window_set_policy (GTK_WINDOW (w_current->main_window), TRUE, TRUE, TRUE);
00266 
00267   /* We want the widgets to flow around the drawing area, so we don't
00268    * set a size of the main window.  The drawing area's size is fixed,
00269    * see below
00270    */
00271 
00272    /* 
00273     * normally we let the window manager handle locating and sizing
00274     * the window.  However, for some batch processing of schematics
00275     * (generating a pdf of all schematics for example) we want to
00276     * override this.  Hence "auto_place_mode".
00277     */
00278    if( auto_place_mode )
00279     gtk_widget_set_uposition (w_current->main_window, 10, 10);
00280 
00281   /* this should work fine */
00282   g_signal_connect (G_OBJECT (w_current->main_window), "delete_event",
00283                     G_CALLBACK (i_callback_close_wm),
00284                     w_current);
00285 
00286   /* Containers first */
00287   main_box = gtk_vbox_new(FALSE, 1);
00288   gtk_container_border_width(GTK_CONTAINER(main_box), 0);
00289   gtk_container_add(GTK_CONTAINER(w_current->main_window), main_box);
00290 
00291   menubar = get_main_menu (w_current);
00292   if (w_current->handleboxes) {
00293     handlebox = gtk_handle_box_new ();
00294     gtk_box_pack_start(GTK_BOX(main_box), handlebox, FALSE, FALSE, 0);
00295     gtk_container_add (GTK_CONTAINER (handlebox), menubar);
00296   } else {
00297     gtk_box_pack_start(GTK_BOX(main_box), menubar, FALSE, FALSE, 0);
00298   }
00299 
00300   w_current->menubar = menubar;
00301   gtk_widget_realize (w_current->main_window);
00302 
00303   if (w_current->handleboxes && w_current->toolbars) {
00304     handlebox = gtk_handle_box_new ();
00305     gtk_box_pack_start (GTK_BOX (main_box), handlebox, FALSE, FALSE, 0);
00306   }
00307  
00308   if (w_current->toolbars) {
00309     toolbar = gtk_toolbar_new();
00310     gtk_toolbar_set_orientation (GTK_TOOLBAR(toolbar), 
00311                                  GTK_ORIENTATION_HORIZONTAL);
00312     gtk_toolbar_set_style (GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
00313 
00314     if (w_current->handleboxes) {
00315       gtk_container_add (GTK_CONTAINER (handlebox), toolbar);
00316     } else {
00317       gtk_box_pack_start(GTK_BOX(main_box), toolbar, FALSE, FALSE, 0);
00318     }
00319 
00320     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00321                              _("New"), 
00322                              _("New file"), 
00323                              "toolbar/new", 
00324                              x_window_stock_pixmap("new", w_current),
00325                              (GtkSignalFunc) i_callback_toolbar_file_new, 
00326                              w_current);
00327     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00328                              _("Open"), 
00329                              _("Open file..."), 
00330                              "toolbar/open",
00331                              x_window_stock_pixmap("open", w_current),
00332                              (GtkSignalFunc) i_callback_toolbar_file_open, 
00333                              w_current);
00334     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00335                              _("Save"), 
00336                              _("Save file"), 
00337                              "toolbar/save", 
00338                              x_window_stock_pixmap("save", w_current),
00339                              (GtkSignalFunc) i_callback_toolbar_file_save, 
00340                              w_current);
00341     gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 
00342     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00343                              _("Undo"), 
00344                              _("Undo last operation"), 
00345                              "toolbar/undo", 
00346                              x_window_stock_pixmap("undo", w_current),
00347                              (GtkSignalFunc) i_callback_toolbar_edit_undo, 
00348                              w_current);
00349     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00350                              _("Redo"), 
00351                              _("Redo last undo"), 
00352                              "toolbar/redo", 
00353                              x_window_stock_pixmap("redo", w_current),
00354                              (GtkSignalFunc) i_callback_toolbar_edit_redo, 
00355                              w_current);
00356     gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 
00357     /* not part of any radio button group */
00358     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00359                              _("Component"), 
00360                              _("Add component...\nSelect library and component from list, move the mouse into main window, click to place\nRight mouse button to cancel"), 
00361                              "toolbar/component", 
00362                              x_window_stock_pixmap("comp", w_current),
00363                              (GtkSignalFunc) i_callback_toolbar_add_component, 
00364                              w_current);
00365     w_current->toolbar_net = 
00366       gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
00367                                  GTK_TOOLBAR_CHILD_RADIOBUTTON,
00368                                  NULL,
00369                                  _("Nets"),
00370                                  _("Add nets mode\nRight mouse button to cancel"),
00371                                  "toolbar/nets",
00372                                  x_window_stock_pixmap("net", w_current),
00373                                  (GtkSignalFunc) i_callback_toolbar_add_net,
00374                                  w_current);
00375     w_current->toolbar_bus = 
00376       gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
00377                                  GTK_TOOLBAR_CHILD_RADIOBUTTON,
00378                                  w_current->toolbar_net,
00379                                  _("Bus"),
00380                                  _("Add buses mode\nRight mouse button to cancel"),
00381                                  "toolbar/bus",
00382                                  x_window_stock_pixmap("bus", w_current),
00383                                  (GtkSignalFunc) i_callback_toolbar_add_bus,
00384                                  w_current);
00385     /* not part of any radio button group */
00386     gtk_toolbar_append_item (GTK_TOOLBAR (toolbar), 
00387                              _("Text"), 
00388                              _("Add Text..."), 
00389                              "toolbar/text", 
00390                              x_window_stock_pixmap("text", w_current),
00391                              (GtkSignalFunc) i_callback_toolbar_add_text, 
00392                              w_current);
00393     gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 
00394     w_current->toolbar_select = 
00395       gtk_toolbar_append_element(GTK_TOOLBAR(toolbar),
00396                                  GTK_TOOLBAR_CHILD_RADIOBUTTON,
00397                                  w_current->toolbar_bus,
00398                                  _("Select"),
00399                                  _("Select mode"),
00400                                  "toolbar/select",
00401                                  x_window_stock_pixmap("select", w_current),
00402                                  (GtkSignalFunc) i_callback_toolbar_edit_select, 
00403                                  w_current);
00404 
00405 
00406     gtk_toolbar_append_space (GTK_TOOLBAR(toolbar)); 
00407     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w_current->toolbar_select),
00408                                  TRUE);
00409   } 
00410 
00411 
00412   /*  Try to create popup menu (appears in right mouse button  */
00413   w_current->popup_menu = (GtkWidget *) get_main_popup(w_current);
00414 
00415   drawbox = gtk_hbox_new(FALSE, 0);
00416   gtk_container_border_width(GTK_CONTAINER(drawbox), 0);
00417   gtk_container_add(GTK_CONTAINER(main_box), drawbox);
00418 
00419   x_window_create_drawing(drawbox, w_current);
00420   x_window_setup_draw_events(w_current);
00421 
00422   if (w_current->scrollbars_flag == TRUE) {
00423     /* setup scroll bars */
00424     w_current->v_adjustment = GTK_ADJUSTMENT (
00425       gtk_adjustment_new (toplevel->init_bottom, 0.0, toplevel->init_bottom,
00426                           100.0, 100.0, 10.0));
00427 
00428     w_current->v_scrollbar = gtk_vscrollbar_new (w_current->v_adjustment);
00429 
00430     gtk_range_set_update_policy (GTK_RANGE (w_current->v_scrollbar),
00431                                  GTK_UPDATE_CONTINUOUS);
00432 
00433     gtk_box_pack_start (GTK_BOX (drawbox), w_current->v_scrollbar,
00434                         FALSE, FALSE, 0);
00435 
00436     g_signal_connect (w_current->v_adjustment,
00437                       "value_changed",
00438                       G_CALLBACK (x_event_vschanged),
00439                       w_current);
00440 
00441     w_current->h_adjustment = GTK_ADJUSTMENT (
00442       gtk_adjustment_new (0.0, 0.0, toplevel->init_right, 100.0, 100.0, 10.0));
00443 
00444     w_current->h_scrollbar = gtk_hscrollbar_new (w_current->h_adjustment);
00445 
00446     gtk_range_set_update_policy (GTK_RANGE (w_current->h_scrollbar),
00447                                  GTK_UPDATE_CONTINUOUS);
00448 
00449     gtk_box_pack_start (GTK_BOX (main_box), w_current->h_scrollbar,
00450                         FALSE, FALSE, 0);
00451 
00452     g_signal_connect (w_current->h_adjustment,
00453                       "value_changed",
00454                       G_CALLBACK (x_event_hschanged),
00455                       w_current);
00456   }
00457 
00458   /* macro box */
00459   w_current->macro_entry = gtk_entry_new();
00460   g_signal_connect(w_current->macro_entry, "activate",
00461            G_CALLBACK(&x_window_invoke_macro), w_current);
00462 
00463   w_current->macro_box = gtk_hbox_new(FALSE, 0);
00464   gtk_box_pack_start(GTK_BOX (w_current->macro_box),
00465                      gtk_label_new (_("Evaluate:")), FALSE, FALSE, 2);
00466   gtk_box_pack_start(GTK_BOX(w_current->macro_box), w_current->macro_entry,
00467              TRUE, TRUE, 2);
00468   gtk_container_border_width(GTK_CONTAINER(w_current->macro_box), 1);
00469   gtk_box_pack_start (GTK_BOX (main_box), w_current->macro_box,
00470               FALSE, FALSE, 0);
00471 
00472   /* bottom box */
00473   bottom_box = gtk_hbox_new(FALSE, 0);
00474   gtk_container_border_width(GTK_CONTAINER(bottom_box), 1);
00475   gtk_box_pack_start (GTK_BOX (main_box), bottom_box, FALSE, FALSE, 0);
00476 
00477   /*    label = gtk_label_new ("Mouse buttons:");
00478         gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 10);
00479   */
00480 
00481   label = gtk_label_new (" ");
00482   gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 2);
00483 
00484   w_current->left_label = gtk_label_new (_("Pick"));
00485   gtk_box_pack_start (GTK_BOX (bottom_box), w_current->left_label,
00486                       FALSE, FALSE, 0);
00487 
00488   label = gtk_label_new ("|");
00489   gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5);
00490 
00491   if (w_current->middle_button == STROKE) {
00492 #ifdef HAVE_LIBSTROKE
00493     w_current->middle_label = gtk_label_new (_("Stroke"));
00494 #else
00495     w_current->middle_label = gtk_label_new (_("none"));
00496 #endif
00497   } else if (w_current->middle_button == ACTION) {
00498     w_current->middle_label = gtk_label_new (_("Action"));
00499   } else {
00500     w_current->middle_label = gtk_label_new (_("Repeat/none"));
00501   }
00502 
00503   gtk_box_pack_start (GTK_BOX (bottom_box), w_current->middle_label,
00504                       FALSE, FALSE, 0);
00505 
00506   label = gtk_label_new ("|");
00507   gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5);
00508 
00509   if (default_third_button == POPUP_ENABLED) {
00510     w_current->right_label = gtk_label_new (_("Menu/Cancel"));
00511   } else {
00512     w_current->right_label = gtk_label_new (_("Pan/Cancel"));
00513   }
00514   gtk_box_pack_start (GTK_BOX (bottom_box), w_current->right_label,
00515                       FALSE, FALSE, 0);
00516 
00517   label = gtk_label_new (" ");
00518   gtk_box_pack_start (GTK_BOX (bottom_box), label, FALSE, FALSE, 5);
00519 
00520   w_current->grid_label = gtk_label_new (" ");
00521   gtk_box_pack_start (GTK_BOX (bottom_box), w_current->grid_label,
00522                       FALSE, FALSE, 10);
00523 
00524   w_current->status_label = gtk_label_new (_("Select Mode"));
00525   gtk_box_pack_end (GTK_BOX (bottom_box), w_current->status_label, FALSE,
00526                     FALSE, 10);
00527 
00528   gtk_widget_show_all (w_current->main_window);
00529   gtk_widget_hide(w_current->macro_box);
00530 
00531   w_current->window = w_current->drawing_area->window;
00532 
00533   w_current->drawable = w_current->window;
00534 
00535   x_window_setup_gc(w_current);
00536 }
00537 
00543 void x_window_close(GSCHEM_TOPLEVEL *w_current)
00544 {
00545   TOPLEVEL *toplevel = w_current->toplevel;
00546   gboolean last_window = FALSE;
00547 
00548   /* If we're closing whilst inside a move action, re-wind the
00549    * page contents back to their state before we started */
00550   if (w_current->inside_action &&
00551       (w_current->event_state == MOVE ||
00552        w_current->event_state == ENDMOVE)) {
00553     o_move_cancel (w_current);
00554   }
00555 
00556   /* last chance to save possible unsaved pages */
00557   if (!x_dialog_close_window (w_current)) {
00558     /* user somehow cancelled the close */
00559     return;
00560   }
00561 
00562   x_clipboard_finish (w_current);
00563 
00564 #if DEBUG
00565   o_conn_print_hash(w_current->page_current->conn_table);
00566 #endif
00567 
00568   /* close all the dialog boxes */
00569   if (w_current->sowindow)
00570   gtk_widget_destroy(w_current->sowindow);
00571 
00572   if (w_current->cswindow)
00573   gtk_widget_destroy(w_current->cswindow);
00574 
00575   if (w_current->tiwindow)
00576   gtk_widget_destroy(w_current->tiwindow);
00577 
00578   if (w_current->tewindow)
00579   gtk_widget_destroy(w_current->tewindow);
00580 
00581   if (w_current->aawindow)
00582   gtk_widget_destroy(w_current->aawindow);
00583 
00584   x_multiattrib_close (w_current);
00585 
00586   if (w_current->aewindow)
00587   gtk_widget_destroy(w_current->aewindow);
00588 
00589   if (w_current->trwindow)
00590   gtk_widget_destroy(w_current->trwindow);
00591 
00592   x_pagesel_close (w_current);
00593 
00594   if (w_current->tswindow)
00595   gtk_widget_destroy(w_current->tswindow);
00596 
00597   if (w_current->iwindow)
00598   gtk_widget_destroy(w_current->iwindow);
00599 
00600   if (w_current->hkwindow)
00601   gtk_widget_destroy(w_current->hkwindow);
00602 
00603   if (w_current->cowindow)
00604   gtk_widget_destroy(w_current->cowindow);
00605 
00606   if (w_current->clwindow)
00607   gtk_widget_destroy(w_current->clwindow);
00608 
00609   if (w_current->sewindow)
00610   gtk_widget_destroy(w_current->sewindow);
00611 
00612   if (g_list_length (global_window_list) == 1) {
00613     /* no more window after this one, remember to quit */
00614     last_window = TRUE;
00615   }
00616 
00617   if (toplevel->major_changed_refdes) {
00618     GList* current = toplevel->major_changed_refdes;
00619     while (current)
00620     {
00621       /* printf("yeah freeing: %s\n", (char*) current->data); */
00622       g_free(current->data);
00623       current = g_list_next(current);
00624     }
00625     g_list_free(toplevel->major_changed_refdes);
00626   }
00627 
00628   /* stuff that has to be done before we free w_current */
00629   if (last_window) {
00630     /* close the log file */
00631     s_log_close ();
00632     /* free the buffers */
00633     o_buffer_free (w_current);
00634   }
00635 
00636   x_window_free_gc(w_current);
00637 
00638   /* Clear Guile smob weak ref */
00639   if (w_current->smob != SCM_UNDEFINED) {
00640     SCM_SET_SMOB_DATA (w_current->smob, NULL);
00641     w_current->smob = SCM_UNDEFINED;
00642   }
00643 
00644   /* finally close the main window */
00645   gtk_widget_destroy(w_current->main_window);
00646 
00647   s_toplevel_delete (toplevel);
00648   global_window_list = g_list_remove (global_window_list, w_current);
00649   g_free (w_current);
00650 
00651   /* just closed last window, so quit */
00652   if (last_window) {
00653     gschem_quit();
00654   }
00655 }
00656 
00662 void x_window_close_all(GSCHEM_TOPLEVEL *w_current)
00663 {
00664   GSCHEM_TOPLEVEL *current;
00665   GList *list_copy, *iter;
00666 
00667   iter = list_copy = g_list_copy (global_window_list);
00668   while (iter != NULL ) {
00669     current = (GSCHEM_TOPLEVEL *)iter->data;
00670     iter = g_list_next (iter);
00671     x_window_close (current);
00672   }
00673   g_list_free (list_copy);
00674 }
00675 
00699 PAGE*
00700 x_window_open_page (GSCHEM_TOPLEVEL *w_current, const gchar *filename)
00701 {
00702   TOPLEVEL *toplevel = w_current->toplevel;
00703   PAGE *old_current, *page;
00704   gchar *fn;
00705 
00706   g_return_val_if_fail (toplevel != NULL, NULL);
00707 
00708   /* Generate untitled filename if none was specified */
00709   if (filename == NULL) {
00710     gchar *cwd, *tmp;
00711     cwd = g_get_current_dir ();
00712     tmp = g_strdup_printf ("%s_%d.sch",
00713                            toplevel->untitled_name,
00714                            ++w_current->num_untitled);
00715     fn = g_build_filename (cwd, tmp, NULL);
00716     g_free(cwd);
00717     g_free(tmp);
00718   } else {
00719     fn = g_strdup (filename);
00720   }
00721 
00722   /* Return existing page if it is already loaded */
00723   page = s_page_search (toplevel, fn);
00724   if ( page != NULL ) {
00725     g_free(fn);
00726     return page;
00727   }
00728 
00729   old_current = toplevel->page_current;
00730   page = s_page_new (toplevel, fn);
00731   s_page_goto (toplevel, page);
00732 
00733   /* Load from file if necessary, otherwise just print a message */
00734   if (filename != NULL) {
00735     GError *err = NULL;
00736     if (!quiet_mode)
00737       s_log_message (_("Loading schematic [%s]\n"), fn);
00738 
00739     if (!f_open (toplevel, page, (gchar *) fn, &err)) {
00740       GtkWidget *dialog;
00741 
00742       g_warning ("%s\n", err->message);
00743       dialog = gtk_message_dialog_new_with_markup
00744         (GTK_WINDOW (w_current->main_window),
00745          GTK_DIALOG_DESTROY_WITH_PARENT,
00746          GTK_MESSAGE_ERROR,
00747          GTK_BUTTONS_CLOSE,
00748          _("<b>An error occurred while loading the requested file.</b>\n\nLoading from '%s' failed: %s. The gschem log may contain more information."),
00749          fn, err->message);
00750       gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to load file"));
00751       gtk_dialog_run (GTK_DIALOG (dialog));
00752       gtk_widget_destroy (dialog);
00753       g_error_free (err);
00754     } else {
00755       gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(fn, NULL, NULL));
00756     }
00757   } else {
00758     if (!quiet_mode)
00759       s_log_message (_("New file [%s]\n"),
00760                      toplevel->page_current->page_filename);
00761 
00762     g_run_hook_page (w_current, "%new-page-hook", toplevel->page_current);
00763   }
00764 
00765   a_zoom_extents (w_current,
00766                   s_page_objects (toplevel->page_current),
00767                   A_PAN_DONT_REDRAW);
00768 
00769   o_undo_savestate (w_current, UNDO_ALL);
00770 
00771   if ( old_current != NULL )
00772     s_page_goto (toplevel, old_current);
00773 
00774   /* This line is generally un-needed, however if some code
00775    * wants to open a page, yet not bring it to the front, it is
00776    * needed needed to add it into the page manager. Otherwise,
00777    * it will get done in x_window_set_current_page(...)
00778    */
00779   x_pagesel_update (w_current); /* ??? */
00780 
00781   g_free (fn);
00782 
00783   return page;
00784 }
00785 
00799 void
00800 x_window_set_current_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
00801 {
00802   TOPLEVEL *toplevel = w_current->toplevel;
00803 
00804   g_return_if_fail (toplevel != NULL);
00805   g_return_if_fail (page != NULL);
00806 
00807   o_redraw_cleanstates (w_current);
00808 
00809   s_page_goto (toplevel, page);
00810 
00811   i_update_menus (w_current);
00812   i_set_filename (w_current, page->page_filename);
00813 
00814   x_pagesel_update (w_current);
00815   x_multiattrib_update (w_current);
00816 
00817   x_manual_resize (w_current);
00818   x_hscrollbar_update (w_current);
00819   x_vscrollbar_update (w_current);
00820 
00821   o_invalidate_all (w_current);
00822 }
00823 
00841 gint
00842 x_window_save_page (GSCHEM_TOPLEVEL *w_current, PAGE *page, const gchar *filename)
00843 {
00844   TOPLEVEL *toplevel = w_current->toplevel;
00845   PAGE *old_current;
00846   const gchar *log_msg, *state_msg;
00847   gint ret;
00848   GError *err = NULL;
00849 
00850   g_return_val_if_fail (toplevel != NULL, 0);
00851   g_return_val_if_fail (page     != NULL, 0);
00852   g_return_val_if_fail (filename != NULL, 0);
00853 
00854   /* save current page for restore after opening */
00855   old_current = toplevel->page_current;
00856 
00857   /* change to page */
00858   s_page_goto (toplevel, page);
00859   /* and try saving current page to filename */
00860   ret = (gint)f_save (toplevel, toplevel->page_current, filename, &err);
00861   if (ret != 1) {
00862     log_msg   = _("Could NOT save page [%s]\n");
00863     state_msg = _("Error while trying to save");
00864 
00865     GtkWidget *dialog;
00866 
00867     dialog = gtk_message_dialog_new (GTK_WINDOW (w_current->main_window),
00868                                      GTK_DIALOG_DESTROY_WITH_PARENT,
00869                                      GTK_MESSAGE_ERROR,
00870                                      GTK_BUTTONS_CLOSE,
00871                                      "%s",
00872                                      err->message);
00873     gtk_window_set_title (GTK_WINDOW (dialog), _("Failed to save file"));
00874     gtk_dialog_run (GTK_DIALOG (dialog));
00875     gtk_widget_destroy (dialog);
00876     g_clear_error (&err);
00877   } else {
00878     /* successful save of page to file, update page... */
00879     /* change page name if necessary and prepare log message */
00880     if (g_ascii_strcasecmp (page->page_filename, filename) != 0) {
00881       g_free (page->page_filename);
00882       page->page_filename = g_strdup (filename);
00883 
00884       log_msg = _("Saved as [%s]\n");
00885     } else {
00886       log_msg = _("Saved [%s]\n");
00887     }
00888     state_msg = _("Saved");
00889 
00890     /* reset page CHANGED flag */
00891     page->CHANGED = 0;
00892 
00893     /* add to recent file list */
00894     gtk_recent_manager_add_item (recent_manager, g_filename_to_uri(filename, NULL, NULL));
00895   }
00896 
00897   /* log status of operation */
00898   s_log_message (log_msg, filename);
00899 
00900   /* update display and page manager */
00901   x_window_set_current_page (w_current, old_current);
00902 
00903   i_set_state_msg  (w_current, SELECT, state_msg);
00904   i_update_toolbar (w_current);
00905 
00906   return ret;
00907 }
00908 
00920 void
00921 x_window_close_page (GSCHEM_TOPLEVEL *w_current, PAGE *page)
00922 {
00923   TOPLEVEL *toplevel = w_current->toplevel;
00924   PAGE *new_current = NULL;
00925   GList *iter;
00926 
00927   g_return_if_fail (toplevel != NULL);
00928   g_return_if_fail (page     != NULL);
00929 
00930   g_assert (page->pid != -1);
00931 
00932   /* If we're closing whilst inside a move action, re-wind the
00933    * page contents back to their state before we started */
00934   if (w_current->inside_action &&
00935       (w_current->event_state == MOVE ||
00936        w_current->event_state == ENDMOVE)) {
00937     o_move_cancel (w_current);
00938   }
00939 
00940   if (page == toplevel->page_current) {
00941     /* as it will delete current page, select new current page */
00942     /* first look up in page hierarchy */
00943     new_current = s_page_search_by_page_id (toplevel->pages, page->up);
00944 
00945     if (new_current == NULL) {
00946       /* no up in hierarchy, choice is prev, next, new page */
00947       iter = g_list_find( geda_list_get_glist( toplevel->pages ), page );
00948 
00949       if ( g_list_previous( iter ) ) {
00950         new_current = (PAGE *)g_list_previous( iter )->data;
00951       } else if ( g_list_next( iter ) ) {
00952         new_current = (PAGE *)g_list_next( iter )->data;
00953       } else {
00954         /* need to add a new untitled page */
00955         new_current = NULL;
00956       }
00957     }
00958     /* new_current will be the new current page at the end of the function */
00959   }
00960 
00961   s_log_message (page->CHANGED ?
00962                  _("Discarding page [%s]\n") : _("Closing [%s]\n"),
00963                  page->page_filename);
00964   /* remove page from toplevel list of page and free */
00965   s_page_delete (toplevel, page);
00966 
00967   /* Switch to a different page if we just removed the current */
00968   if (toplevel->page_current == NULL) {
00969 
00970     /* Create a new page if there wasn't another to switch to */
00971     if (new_current == NULL) {
00972       new_current = x_window_open_page (w_current, NULL);
00973     }
00974 
00975     /* change to new_current and update display */
00976     x_window_set_current_page (w_current, new_current);
00977   }
00978 }
00979 
00980 
00987 void x_window_set_default_icon( void )
00988 {
00989   gtk_window_set_default_icon_name( GSCHEM_THEME_ICON_NAME );
00990 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines