1 /* Lepton EDA Schematic Capture
2 * Copyright (C) 1998-2010 Ales Hvezda
3 * Copyright (C) 1998-2015 gEDA Contributors
4 * Copyright (C) 2017-2021 Lepton EDA Contributors
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <math.h>
24 #ifdef HAVE_UNISTD_H
25 #include <unistd.h>
26 #endif
27
28 #include "gschem.h"
29
30 /*! \todo Finish function documentation!!!
31 * \brief
32 * \par Function Description
33 *
34 */
35 void
o_component_prepare_place(GschemToplevel * w_current,const CLibSymbol * sym)36 o_component_prepare_place (GschemToplevel *w_current,
37 const CLibSymbol *sym)
38 {
39 GList *temp_list;
40 LeptonObject *o_current;
41 char *buffer;
42 const gchar *sym_name = s_clib_symbol_get_name (sym);
43 GError *err = NULL;
44
45 LeptonPage *active_page = schematic_window_get_active_page (w_current);
46
47 i_set_state (w_current, COMPMODE);
48 i_action_start (w_current);
49
50 /* remove the old place list if it exists */
51 lepton_object_list_delete (active_page->place_list);
52 active_page->place_list = NULL;
53
54 /* Insert the new object into the buffer at world coordinates (0,0).
55 * It will be translated to the mouse coordinates during placement. */
56
57 w_current->first_wx = 0;
58 w_current->first_wy = 0;
59
60 if (w_current->include_component) {
61
62 temp_list = NULL;
63
64 buffer = s_clib_symbol_get_data (sym);
65 temp_list = o_read_buffer (active_page,
66 temp_list,
67 buffer, -1,
68 sym_name,
69 &err);
70 g_free (buffer);
71
72 if (err) {
73 /* If an error occurs here, we can assume that the preview also has failed to load,
74 and the error message is displayed there. We therefore ignore this error, but
75 end the component insertion.
76 */
77
78 g_error_free(err);
79 i_set_state (w_current, SELECT);
80 i_action_stop (w_current);
81 return;
82 }
83
84 /* Take the added objects */
85 active_page->place_list =
86 g_list_concat (active_page->place_list, temp_list);
87
88 } else { /* if (w_current->include_component) {..} else { */
89 LeptonObject *new_object;
90
91 new_object = lepton_component_new (active_page,
92 default_color_id(),
93 0,
94 0,
95 0,
96 0,
97 sym,
98 sym_name,
99 1);
100
101 if (lepton_component_object_get_missing (new_object)) {
102 /* If created object is missing, the loading failed and we
103 end the insert action. */
104 lepton_object_delete (new_object);
105 i_set_state (w_current, SELECT);
106 i_action_stop (w_current);
107 return;
108 }
109 else {
110
111 active_page->place_list =
112 g_list_concat (active_page->place_list,
113 lepton_component_promote_attribs (new_object));
114 active_page->place_list =
115 g_list_append (active_page->place_list, new_object);
116
117 /* Flag the symbol as embedded if necessary */
118 o_current = (LeptonObject*) (g_list_last (active_page->place_list))->data;
119 if (w_current->embed_component) {
120 lepton_component_object_set_embedded (o_current, TRUE);
121 }
122 }
123 }
124
125 /* Run the component place list changed hook without redrawing */
126 /* since the place list is going to be redrawn afterwards */
127 o_component_place_changed_run_hook (w_current);
128 }
129
130
131 /*! \brief Run the component place list changed hook.
132 * \par Function Description
133 * The component place list is usually used when placing new components
134 * in the schematic. This function should be called whenever that list
135 * is modified.
136 * \param [in] w_current GschemToplevel structure.
137 *
138 */
139 void
o_component_place_changed_run_hook(GschemToplevel * w_current)140 o_component_place_changed_run_hook (GschemToplevel *w_current)
141 {
142 GList *ptr = NULL;
143 LeptonPage *active_page = schematic_window_get_active_page (w_current);
144
145 /* Run the component place list changed hook */
146 if (scm_is_false (scm_hook_empty_p (complex_place_list_changed_hook)) &&
147 active_page->place_list != NULL)
148 {
149 ptr = active_page->place_list;
150
151 scm_dynwind_begin ((scm_t_dynwind_flags) 0);
152 g_dynwind_window (w_current);
153 while (ptr) {
154 SCM expr = scm_list_3 (scm_from_utf8_symbol ("run-hook"),
155 complex_place_list_changed_hook,
156 edascm_from_object ((LeptonObject *) ptr->data));
157 g_scm_eval_protected (expr, scm_interaction_environment ());
158 ptr = g_list_next(ptr);
159 }
160 scm_dynwind_end ();
161 }
162 }
163
164
165 /*! \todo Finish function documentation!!!
166 * \brief
167 * \par Function Description
168 *
169 * \note
170 * don't know if this belongs yet
171 */
172 void
o_component_translate_all(GschemToplevel * w_current,int offset)173 o_component_translate_all (GschemToplevel *w_current, int offset)
174 {
175 int w_rleft, w_rtop, w_rright, w_rbottom;
176 LeptonObject *o_current;
177 const GList *iter;
178 int x, y;
179 GschemPageView *view = gschem_toplevel_get_current_page_view (w_current);
180 g_return_if_fail (view != NULL);
181
182 LeptonPage *active_page = schematic_window_get_active_page (w_current);
183
184 gboolean show_hidden_text =
185 gschem_toplevel_get_show_hidden_text (w_current);
186
187 /* first zoom extents */
188 gschem_page_view_zoom_extents (view, NULL);
189 gschem_page_view_invalidate_all (view);
190
191 world_get_object_glist_bounds (lepton_page_objects (active_page),
192 show_hidden_text,
193 &w_rleft, &w_rtop,
194 &w_rright, &w_rbottom);
195
196 /*! \todo do we want snap grid here? */
197 x = snap_grid (w_current, w_rleft);
198 /* WARNING: w_rtop isn't the top of the bounds, it is the smaller
199 * y_coordinate, which represents in the bottom in world coords.
200 * These variables are as named from when screen-coords (which had
201 * the correct sense) were in use . */
202 y = snap_grid (w_current, w_rtop);
203
204 for (iter = lepton_page_objects (active_page);
205 iter != NULL; iter = g_list_next (iter)) {
206 o_current = (LeptonObject*) iter->data;
207 s_conn_remove_object_connections (o_current);
208 }
209
210 if (offset == 0) {
211 g_message (_("Translating schematic [%1$d %2$d]"), -x, -y);
212 lepton_object_list_translate (lepton_page_objects (active_page), -x, -y);
213 } else {
214 g_message (_("Translating schematic [%1$d %2$d]"),
215 offset, offset);
216 lepton_object_list_translate (lepton_page_objects (active_page), offset, offset);
217 }
218
219 for (iter = lepton_page_objects (active_page);
220 iter != NULL; iter = g_list_next (iter)) {
221 o_current = (LeptonObject*) iter->data;
222 s_conn_update_object (active_page, o_current);
223 }
224
225 /* this is an experimental mod, to be able to translate to all
226 * places */
227 gschem_page_view_zoom_extents (view, NULL);
228 if (!w_current->SHIFTKEY) o_select_unselect_all(w_current);
229 gschem_page_view_invalidate_all (view);
230 gschem_toplevel_page_content_changed (w_current, active_page);
231 o_undo_savestate_old(w_current, UNDO_ALL);
232 i_update_menus(w_current);
233 }
234