gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2011 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 00022 #include <stdio.h> 00023 #include <math.h> 00024 #ifdef HAVE_UNISTD_H 00025 #include <unistd.h> 00026 #endif 00027 00028 #include "gschem.h" 00029 #include <missing.h> 00030 00031 #ifdef HAVE_LIBDMALLOC 00032 #include <dmalloc.h> 00033 #endif 00034 00040 void o_complex_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) 00041 { 00042 g_return_if_fail (o_current != NULL); 00043 g_return_if_fail (o_current->complex != NULL); 00044 00045 o_redraw(w_current, o_current->complex->prim_objs, TRUE); 00046 } 00047 00048 00054 void o_complex_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *object) 00055 { 00056 g_assert( (object->type == OBJ_COMPLEX || 00057 object->type == OBJ_PLACEHOLDER) ); 00058 00059 o_glist_draw_place (w_current, dx, dy, object->complex->prim_objs); 00060 } 00061 00062 00068 void o_complex_prepare_place(GSCHEM_TOPLEVEL *w_current, const CLibSymbol *sym) 00069 { 00070 TOPLEVEL *toplevel = w_current->toplevel; 00071 GList *temp_list; 00072 OBJECT *o_current; 00073 char *buffer; 00074 const gchar *sym_name = s_clib_symbol_get_name (sym); 00075 GError *err = NULL; 00076 00077 /* remove the old place list if it exists */ 00078 s_delete_object_glist(toplevel, toplevel->page_current->place_list); 00079 toplevel->page_current->place_list = NULL; 00080 00081 /* Insert the new object into the buffer at world coordinates (0,0). 00082 * It will be translated to the mouse coordinates during placement. */ 00083 00084 w_current->first_wx = 0; 00085 w_current->first_wy = 0; 00086 00087 if (w_current->include_complex) { 00088 00089 temp_list = NULL; 00090 00091 buffer = s_clib_symbol_get_data (sym); 00092 temp_list = o_read_buffer (toplevel, 00093 temp_list, 00094 buffer, -1, 00095 sym_name, 00096 &err); 00097 g_free (buffer); 00098 00099 if (err) { 00100 /* If an error occurs here, we can assume that the preview also has failed to load, 00101 and the error message is displayed there. We therefore ignore this error, but 00102 end the component insertion. 00103 */ 00104 00105 g_error_free(err); 00106 i_set_state (w_current, SELECT); 00107 return; 00108 } 00109 00110 /* Take the added objects */ 00111 toplevel->page_current->place_list = 00112 g_list_concat (toplevel->page_current->place_list, temp_list); 00113 00114 } else { /* if (w_current->include_complex) {..} else { */ 00115 OBJECT *new_object; 00116 00117 new_object = o_complex_new (toplevel, OBJ_COMPLEX, DEFAULT_COLOR, 00118 0, 0, 0, 0, sym, sym_name, 1); 00119 00120 if (new_object->type == OBJ_PLACEHOLDER) { 00121 /* If created object is a placeholder, the loading failed and we end the insert action */ 00122 00123 s_delete_object(toplevel, new_object); 00124 i_set_state (w_current, SELECT); 00125 return; 00126 } 00127 else { 00128 00129 toplevel->page_current->place_list = 00130 g_list_concat (toplevel->page_current->place_list, 00131 o_complex_promote_attribs (toplevel, new_object)); 00132 toplevel->page_current->place_list = 00133 g_list_append (toplevel->page_current->place_list, new_object); 00134 00135 /* Flag the symbol as embedded if necessary */ 00136 o_current = (g_list_last (toplevel->page_current->place_list))->data; 00137 if (w_current->embed_complex) { 00138 o_current->complex_embedded = TRUE; 00139 } 00140 } 00141 } 00142 00143 /* Run the complex place list changed hook without redrawing */ 00144 /* since the place list is going to be redrawn afterwards */ 00145 o_complex_place_changed_run_hook (w_current); 00146 00147 w_current->inside_action = 1; 00148 i_set_state (w_current, ENDCOMP); 00149 } 00150 00151 00160 void o_complex_place_changed_run_hook(GSCHEM_TOPLEVEL *w_current) { 00161 TOPLEVEL *toplevel = w_current->toplevel; 00162 GList *ptr = NULL; 00163 00164 /* Run the complex place list changed hook */ 00165 if (scm_is_false (scm_hook_empty_p (complex_place_list_changed_hook)) && 00166 toplevel->page_current->place_list != NULL) { 00167 ptr = toplevel->page_current->place_list; 00168 00169 scm_dynwind_begin (0); 00170 g_dynwind_window (w_current); 00171 while (ptr) { 00172 SCM expr = scm_list_3 (scm_from_utf8_symbol ("run-hook"), 00173 complex_place_list_changed_hook, 00174 edascm_from_object ((OBJECT *) ptr->data)); 00175 g_scm_eval_protected (expr, scm_interaction_environment ()); 00176 ptr = g_list_next(ptr); 00177 } 00178 scm_dynwind_end (); 00179 } 00180 } 00181 00182 00190 void o_complex_translate_all(GSCHEM_TOPLEVEL *w_current, int offset) 00191 { 00192 TOPLEVEL *toplevel = w_current->toplevel; 00193 int w_rleft, w_rtop, w_rright, w_rbottom; 00194 OBJECT *o_current; 00195 const GList *iter; 00196 int x, y; 00197 00198 /* first zoom extents */ 00199 a_zoom_extents (w_current, s_page_objects (toplevel->page_current), 00200 A_PAN_DONT_REDRAW); 00201 o_invalidate_all (w_current); 00202 00203 world_get_object_glist_bounds (toplevel, 00204 s_page_objects (toplevel->page_current), 00205 &w_rleft, &w_rtop, 00206 &w_rright, &w_rbottom); 00207 00209 x = snap_grid (w_current, w_rleft); 00210 /* WARNING: w_rtop isn't the top of the bounds, it is the smaller 00211 * y_coordinate, which represents in the bottom in world coords. 00212 * These variables are as named from when screen-coords (which had 00213 * the correct sense) were in use . */ 00214 y = snap_grid (w_current, w_rtop); 00215 00216 for (iter = s_page_objects (toplevel->page_current); 00217 iter != NULL; iter = g_list_next (iter)) { 00218 o_current = iter->data; 00219 s_conn_remove_object (toplevel, o_current); 00220 } 00221 00222 if (offset == 0) { 00223 s_log_message(_("Translating schematic [%d %d]\n"), -x, -y); 00224 o_glist_translate_world (toplevel, -x, -y, 00225 s_page_objects (toplevel->page_current)); 00226 } else { 00227 s_log_message(_("Translating schematic [%d %d]\n"), 00228 offset, offset); 00229 o_glist_translate_world (toplevel, offset, offset, 00230 s_page_objects (toplevel->page_current)); 00231 } 00232 00233 for (iter = s_page_objects (toplevel->page_current); 00234 iter != NULL; iter = g_list_next (iter)) { 00235 o_current = iter->data; 00236 s_conn_update_object (toplevel, o_current); 00237 } 00238 00239 /* this is an experimental mod, to be able to translate to all 00240 * places */ 00241 a_zoom_extents (w_current, s_page_objects (toplevel->page_current), 00242 A_PAN_DONT_REDRAW); 00243 if (!w_current->SHIFTKEY) o_select_unselect_all(w_current); 00244 o_invalidate_all (w_current); 00245 toplevel->page_current->CHANGED=1; 00246 o_undo_savestate(w_current, UNDO_ALL); 00247 i_update_menus(w_current); 00248 }