1 /* Lepton EDA Schematic Capture
2 * Copyright (C) 1998-2010 Ales Hvezda
3 * Copyright (C) 1998-2016 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
25 #include "gschem.h"
26
27 #define GET_BOX_WIDTH(w) abs((w)->second_wx - (w)->first_wx)
28 #define GET_BOX_HEIGHT(w) abs((w)->second_wy - (w)->first_wy)
29
30 #define GET_PICTURE_WIDTH(w) \
31 abs((w)->second_wx - (w)->first_wx)
32 #define GET_PICTURE_HEIGHT(w) \
33 (w)->pixbuf_wh_ratio == 0 ? 0 : abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio
34 #define GET_PICTURE_LEFT(w) \
35 MIN((w)->first_wx, (w)->second_wx)
36 #define GET_PICTURE_TOP(w) \
37 (w)->first_wy > (w)->second_wy ? (w)->first_wy : \
38 (w)->first_wy+abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio
39
40
41 /*! \brief Check if point is inside grip.
42 * \par Function Description
43 * This function is used to determine if the (<B>x</B>,<B>y</B>) point is
44 * inside a grip of one of the selected object on the current sheet.
45 * The <B>x</B> and <B>y</B> parameters are in world units.
46 * If the point is inside one grip, a pointer on the object it belongs to is
47 * returned and <B>*whichone</B> is set according to the position of the grip
48 * on the object.
49 * Else, <B>*whichone</B> is unchanged and the function returns <B>NULL</B>.
50 *
51 * A specific search function is provided for every kind of graphical object.
52 * The list of selected object is covered : each object is tested with the
53 * appropriate function.
54 *
55 * \param [in] w_current The GschemToplevel object.
56 * \param [in] x Current x coordinate of pointer in world units.
57 * \param [in] y Current y coordinate of pointer in world units.
58 * \param [out] whichone Which grip point is selected.
59 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
60 */
o_grips_search_world(GschemToplevel * w_current,int x,int y,int * whichone)61 LeptonObject *o_grips_search_world(GschemToplevel *w_current, int x, int y, int *whichone)
62 {
63 LeptonObject *object=NULL;
64 LeptonObject *found=NULL;
65 GList *s_current;
66 int size;
67 int w_size;
68
69 GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
70 g_return_val_if_fail (page_view != NULL, NULL);
71
72 LeptonPage *active_page = schematic_window_get_active_page (w_current);
73
74 if (!whichone) {
75 return(NULL);
76 }
77
78 /* get the size of the grip according to zoom level */
79 size = GRIP_SIZE / 2;
80 w_size = gschem_page_view_WORLDabs (page_view, size);
81
82 s_current = lepton_list_get_glist (active_page->selection_list );
83 while (s_current != NULL) {
84 object = (LeptonObject *) s_current->data;
85 if (object) {
86 switch (lepton_object_get_type (object)) {
87 case(OBJ_ARC):
88 /* check the grips of the arc object */
89 found = o_grips_search_arc_world(w_current, object,
90 x, y, w_size, whichone);
91 if(found != NULL) return found;
92 break;
93
94 case(OBJ_BOX):
95 /* check the grips of the box object */
96 found = o_grips_search_box_world(w_current, object,
97 x, y, w_size, whichone);
98 if(found != NULL) return found;
99 break;
100
101 case(OBJ_PATH):
102 /* check the grips of the path object */
103 found = o_grips_search_path_world(w_current, object,
104 x, y, w_size, whichone);
105 if(found != NULL) return found;
106 break;
107
108 case(OBJ_PICTURE):
109 /* check the grips of the picture object */
110 found = o_grips_search_picture_world(w_current, object,
111 x, y, w_size, whichone);
112 if(found != NULL) return found;
113 break;
114
115 case(OBJ_CIRCLE):
116 /* check the grips of the circle object */
117 found = o_grips_search_circle_world(w_current, object,
118 x, y, w_size, whichone);
119 if(found != NULL) return found;
120 break;
121
122 case(OBJ_LINE):
123 case(OBJ_PIN):
124 case(OBJ_NET):
125 case(OBJ_BUS):
126 /* check the grips of the line object */
127 /* the function is the same for line, pin, net, bus */
128 found = o_grips_search_line_world(w_current, object,
129 x, y, w_size, whichone);
130 if(found != NULL) return found;
131 break;
132
133 default:
134 break;
135 }
136 }
137 s_current = g_list_next(s_current);
138 }
139
140 return(NULL);
141 }
142
143
144 /*! \brief Check if pointer is inside the grip region.
145 *
146 * \par Function Description
147 * This function checks if the point (<B>x</B>,<B>y</B>) is
148 * inside the grip centered at (<B>grip_x</B>,<B>grip_y</B>).
149 *
150 * \param [in] x Current x coordinate of pointer in world units.
151 * \param [in] y Current y coordinate of pointer in world units.
152 * \param [in] grip_x Current x coordinate of grip center in world units.
153 * \param [in] grip_y Current y coordinate of grip center in world units.
154 * \param [in] size Half the width of the grip square in world units.
155 * \return True / False whether the mouse pointer is inside the grip.
156 */
inside_grip(int x,int y,int grip_x,int grip_y,int size)157 static gboolean inside_grip( int x, int y, int grip_x, int grip_y, int size )
158 {
159 int xmin, ymin, xmax, ymax;
160
161 xmin = grip_x - size;
162 ymin = grip_y - size;
163 xmax = xmin + 2 * size;
164 ymax = ymin + 2 * size;
165
166 return inside_region(xmin, ymin, xmax, ymax, x, y);
167 }
168
169 /*! \brief Check if pointer is inside arc grip.
170 * \par Function Description
171 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
172 * inside one of the grips of an <B>o_current</B> pointed arc object. If so
173 * the <B>whichone</B> pointed integer is set to the number of this grip and
174 * the return pointer is a pointer on this object. If the point is not
175 * inside a grip the function returns a NULL pointer and the <B>whichone</B>
176 * pointed integer is unset.
177 *
178 * An arc object has three grips :
179 * <DL>
180 * <DT>*</DT><DD>one at the center of the arc. This grip is used to modify
181 * the radius of the arc. If this one is selected, the
182 * <B>whichone</B> pointed integer is set to <B>ARC_RADIUS</B>.
183 * <DT>*</DT><DD>one at one end of the arc. It corresponds to the starting
184 * angle of the arc. If this one is selected, the
185 * <B>whichone</B> pointed integer is set to <B>ARC_START_ANGLE</B>.
186 * <DT>*</DT><DD>one at the other end of the arc. It corresponds to the
187 * ending angle of the arc. If this one is selected, the
188 * <B>whichone</B> pointed integer is set to <B>ARC_SWEEP_ANGLE</B>.
189 * </DL>
190 *
191 * The <B>x</B> and <B>y</B> parameters are in world units.
192 *
193 * The <B>size</B> parameter is the width (and height) of the square
194 * representing a grip in world units.
195 *
196 * \param [in] w_current The GschemToplevel object.
197 * \param [in] o_current Arc LeptonObject to check.
198 * \param [in] x Current x coordinate of pointer in world units.
199 * \param [in] y Current y coordinate of pointer in world units.
200 * \param [in] size Half the width of the grip square in world units.
201 * \param [out] whichone Which grip point is selected.
202 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
203 */
o_grips_search_arc_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)204 LeptonObject *o_grips_search_arc_world(GschemToplevel *w_current, LeptonObject *o_current,
205 int x, int y, int size, int *whichone)
206 {
207 int centerx, centery, radius, start_angle, sweep_angle;
208 double tmp;
209
210 centerx = lepton_arc_object_get_center_x (o_current);
211 centery = lepton_arc_object_get_center_y (o_current);
212 radius = lepton_arc_object_get_radius (o_current);
213 start_angle = lepton_arc_object_get_start_angle (o_current);
214 sweep_angle = lepton_arc_object_get_sweep_angle (o_current);
215
216 /* check the grip on the center of the arc */
217 if (inside_grip(x, y, centerx, centery, size)) {
218 *whichone = ARC_RADIUS;
219 return(o_current);
220 }
221
222 /* check the grip at the end angle of the arc */
223 tmp = ((double) start_angle + sweep_angle) * M_PI / 180;
224 if (inside_grip(x, y,
225 centerx + radius * cos(tmp),
226 centery + radius * sin(tmp), size)) {
227 *whichone = ARC_SWEEP_ANGLE;
228 return(o_current);
229 }
230
231 /* check the grip at the start angle of the arc */
232 tmp = ((double) start_angle) * M_PI / 180;
233 if (inside_grip(x, y,
234 centerx + radius * cos(tmp),
235 centery + radius * sin(tmp), size)) {
236 *whichone = ARC_START_ANGLE;
237 return(o_current);
238 }
239
240 return NULL;
241 }
242
243 /*! \brief Check if pointer is inside box grip.
244 * \par Function Description
245 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
246 * inside one of the grips of the <B>o_current</B> pointed box object.
247 * If so, the <B>whichone</B> pointed integer is set to the identifier of
248 * this grip and the returned pointer is a pointer on this object.
249 * If the point is not inside a grip the function returns a NULL pointer
250 * and the <B>whichone</B> pointed integer is unset.
251 *
252 * A box object has four grips : one at each corner of the box. The
253 * identifiers of each corner are <B>BOX_UPPER_LEFT</B>,
254 * <B>BOX_UPPER_RIGHT</B>, <B>BOX_LOWER_LEFT</B> and <B>BOX_LOWER_RIGHT</B>.
255 *
256 * The <B>x</B> and <B>y</B> parameters are in world units.
257 *
258 * The <B>size</B> parameter is half the width (and half the height) of
259 * the square representing a grip in world units.
260 *
261 * \param [in] w_current The GschemToplevel object.
262 * \param [in] o_current Box LeptonObject to check.
263 * \param [in] x Current x coordinate of pointer in world units.
264 * \param [in] y Current y coordinate of pointer in world units.
265 * \param [in] size Half the width of the grip square in world units.
266 * \param [out] whichone Which grip point is selected.
267 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
268 */
o_grips_search_box_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)269 LeptonObject *o_grips_search_box_world(GschemToplevel *w_current, LeptonObject *o_current,
270 int x, int y, int size, int *whichone)
271 {
272 int upper_x, upper_y, lower_x, lower_y;
273
274 upper_x = lepton_box_object_get_upper_x (o_current);
275 upper_y = lepton_box_object_get_upper_y (o_current);
276 lower_x = lepton_box_object_get_lower_x (o_current);
277 lower_y = lepton_box_object_get_lower_y (o_current);
278
279 /* inside upper left grip ? */
280 if (inside_grip (x, y, upper_x, upper_y, size))
281 {
282 *whichone = BOX_UPPER_LEFT;
283 return(o_current);
284 }
285
286 /* inside lower right grip ? */
287 if (inside_grip (x, y, lower_x, lower_y, size))
288 {
289 *whichone = BOX_LOWER_RIGHT;
290 return(o_current);
291 }
292
293 /* inside upper right grip ? */
294 if (inside_grip (x, y, lower_x, upper_y, size))
295 {
296 *whichone = BOX_UPPER_RIGHT;
297 return(o_current);
298 }
299
300 /* inside lower left grip ? */
301 if (inside_grip (x, y, upper_x, lower_y, size))
302 {
303 *whichone = BOX_LOWER_LEFT;
304 return(o_current);
305 }
306
307 return NULL;
308 }
309
310 /*! \brief Check if pointer is inside path grip.
311 * \par Function Description
312 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>)
313 * is inside one of the grips of the <B>o_current</B> pointed path object.
314 * If so, the <B>whichone</B> pointed integer is set to the identifier of
315 * this grip and the returned pointer is a pointer on this object.
316 * If the point is not inside a grip the function returns a NULL pointer
317 * and the <B>whichone</B> pointed integer is unset.
318 *
319 * A path object has four grips : one at each corner of the path.
320 * The identifiers of each corner are #PICTURE_UPPER_LEFT,
321 * #PICTURE_UPPER_RIGHT, #PICTURE_LOWER_LEFT and
322 * #PICTURE_LOWER_RIGHT.
323 *
324 * The <B>x</B> and <B>y</B> parameters are in world units.
325 *
326 * The <B>size</B> parameter is half the width (and half the height) of the
327 * square representing a grip in world units.
328 *
329 * \param [in] w_current The GschemToplevel object.
330 * \param [in] o_current Picture LeptonObject to check.
331 * \param [in] x Current x coordinate of pointer in world units.
332 * \param [in] y Current y coordinate of pointer in world units.
333 * \param [in] size Half the width of the grip square in world units.
334 * \param [out] whichone Which grip point is selected.
335 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
336 */
o_grips_search_path_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)337 LeptonObject *o_grips_search_path_world(GschemToplevel *w_current, LeptonObject *o_current,
338 int x, int y, int size, int *whichone)
339 {
340 LeptonPathSection *section;
341 int i;
342 int grip_no = 0;
343
344 for (i = 0; i < lepton_path_object_get_num_sections (o_current); i++)
345 {
346 section = lepton_path_object_get_section (o_current, i);
347
348 switch (section->code) {
349 case PATH_CURVETO:
350 /* inside first control grip ? */
351 if (inside_grip(x, y, section->x1, section->y1, size)) {
352 *whichone = grip_no;
353 return o_current;
354 }
355 grip_no ++;
356 /* inside second control grip ? */
357 if (inside_grip(x, y, section->x2, section->y2, size)) {
358 *whichone = grip_no;
359 return o_current;
360 }
361 grip_no ++;
362 /* Fall through */
363 case PATH_MOVETO:
364 case PATH_MOVETO_OPEN:
365 case PATH_LINETO:
366 /* inside destination control grip ? */
367 if (inside_grip(x, y, section->x3, section->y3, size)) {
368 *whichone = grip_no;
369 return o_current;
370 }
371 grip_no ++;
372 break;
373 case PATH_END:
374 break;
375 }
376 }
377
378 return NULL;
379 }
380
381 /*! \brief Check if pointer is inside picture grip.
382 * \par Function Description
383 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>)
384 * is inside one of the grips of the <B>o_current</B> pointed picture object.
385 * If so, the <B>whichone</B> pointed integer is set to the identifier of
386 * this grip and the returned pointer is a pointer on this object.
387 * If the point is not inside a grip the function returns a NULL pointer
388 * and the <B>whichone</B> pointed integer is unset.
389 *
390 * A picture object has four grips : one at each corner of the picture.
391 * The identifiers of each corner are #PICTURE_UPPER_LEFT,
392 * #PICTURE_UPPER_RIGHT, #PICTURE_LOWER_LEFT and
393 * #PICTURE_LOWER_RIGHT.
394 *
395 * The <B>x</B> and <B>y</B> parameters are in world units.
396 *
397 * The <B>size</B> parameter is half the width (and half the height) of the
398 * square representing a grip in world units.
399 *
400 * \param [in] w_current The GschemToplevel object.
401 * \param [in] o_current Picture LeptonObject to check.
402 * \param [in] x Current x coordinate of pointer in world units.
403 * \param [in] y Current y coordinate of pointer in world units.
404 * \param [in] size Half the width of the grip square in world units.
405 * \param [out] whichone Which grip point is selected.
406 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
407 */
o_grips_search_picture_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)408 LeptonObject *o_grips_search_picture_world(GschemToplevel *w_current, LeptonObject *o_current,
409 int x, int y, int size, int *whichone)
410 {
411 int lower_x, lower_y, upper_x, upper_y;
412
413 lower_x = lepton_picture_object_get_lower_x (o_current);
414 lower_y = lepton_picture_object_get_lower_y (o_current);
415 upper_x = lepton_picture_object_get_upper_x (o_current);
416 upper_y = lepton_picture_object_get_upper_y (o_current);
417
418 /* inside upper left grip ? */
419 if (inside_grip (x, y, upper_x, upper_y, size))
420 {
421 *whichone = PICTURE_UPPER_LEFT;
422 return(o_current);
423 }
424
425 /* inside lower right grip ? */
426 if (inside_grip (x, y, lower_x, lower_y, size))
427 {
428 *whichone = PICTURE_LOWER_RIGHT;
429 return(o_current);
430 }
431
432 /* inside upper right grip ? */
433 if (inside_grip (x, y, lower_x, upper_y, size))
434 {
435 *whichone = PICTURE_UPPER_RIGHT;
436 return(o_current);
437 }
438
439 /* inside lower left grip ? */
440 if (inside_grip (x, y, upper_x, lower_y, size))
441 {
442 *whichone = PICTURE_LOWER_LEFT;
443 return(o_current);
444 }
445
446 return NULL;
447 }
448
449 /*! \brief Check if pointer is inside circle grip.
450 * \par Function Description
451 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
452 * the grip of the circle object <B>o_current</B>.
453 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
454 * is in one of these areas.
455 * If the event occured in one of the grip, a pointer on the object is
456 * returned and <B>*whichone</B> is set to the identifier of the grip.
457 * If not, the function returns a <B>NULL</B> pointer and <B>*whichone</B>
458 * is unchanged.
459 *
460 * The parameter <B>size</B> is half the size of the grip in world units.
461 *
462 * A circle has only one grip on the lower right corner of the box it
463 * is inscribed in. Moving this grip change the radius of the circle.
464 * The identifier of this grip is <B>CIRCLE_RADIUS</B>.
465 *
466 * \param [in] w_current The GschemToplevel object.
467 * \param [in] o_current Circle LeptonObject to check.
468 * \param [in] x Current x coordinate of pointer in world units.
469 * \param [in] y Current y coordinate of pointer in world units.
470 * \param [in] size Half the width of the grip square in world units.
471 * \param [out] whichone Which grip point is selected.
472 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
473 */
o_grips_search_circle_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)474 LeptonObject *o_grips_search_circle_world(GschemToplevel *w_current, LeptonObject *o_current,
475 int x, int y, int size, int *whichone)
476 {
477 gint center_x = lepton_circle_object_get_center_x (o_current);
478 gint center_y = lepton_circle_object_get_center_y (o_current);
479 gint radius = lepton_circle_object_get_radius (o_current);
480
481 /* check the grip for radius */
482 if (inside_grip(x, y,
483 center_x + radius,
484 center_y - radius,
485 size)) {
486 *whichone = CIRCLE_RADIUS;
487 return(o_current);
488 }
489
490 return NULL;
491 }
492
493 /*! \brief Check if pointer is inside line grip.
494 * \par Function Description
495 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
496 * the grip of the line object <B>o_current</B>.
497 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
498 * is in one of these areas.
499 * If the event occured in one of its grip, a pointer on the object is
500 * returned and <B>*whichone</B> is set to the identifier of the grip. If not,
501 * the function returns <B>NULL</B> pointer and <B>*whichone</B> is unchanged.
502 *
503 * The parameter <B>size</B> is half the size of the grip in world units.
504 *
505 * \param [in] w_current The GschemToplevel object.
506 * \param [in] o_current Line LeptonObject to check.
507 * \param [in] x Current x coordinate of pointer in world units.
508 * \param [in] y Current y coordinate of pointer in world units.
509 * \param [in] size Half the width of the grip square in world units.
510 * \param [out] whichone Which grip point is selected.
511 * \return Pointer to LeptonObject the grip is on, NULL otherwise.
512 */
o_grips_search_line_world(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int size,int * whichone)513 LeptonObject *o_grips_search_line_world(GschemToplevel *w_current, LeptonObject *o_current,
514 int x, int y, int size, int *whichone)
515 {
516 /* check the grip on the end of line 1 */
517 if (inside_grip(x, y,
518 o_current->line->x[LINE_END1],
519 o_current->line->y[LINE_END1], size)) {
520 *whichone = LINE_END1;
521 return(o_current);
522 }
523
524 /* check the grip on the end of line 2 */
525 if (inside_grip(x, y,
526 o_current->line->x[LINE_END2],
527 o_current->line->y[LINE_END2], size)) {
528 *whichone = LINE_END2;
529 return(o_current);
530 }
531
532 return NULL;
533 }
534
535 /*! \brief Initialize grip motion process for an arc.
536 * \par Function Description
537 * This function initializes the grip motion process for an arc.
538 * From the <B>o_current</B> pointed object, it stores into the
539 * GschemToplevel structure the coordinates of the center, the radius
540 * and the two angle that describes an arc. These variables are used in
541 * the grip process.
542 *
543 * The coordinates of the center of the arc on x- and y-axis are stored
544 * into the <B>first_wx</B> and <B>first_wy</B> fields of the GschemToplevel
545 * structure in screen units.
546 *
547 * The radius of the center is stored into the <B>distance</B> field of
548 * the GschemToplevel structure in screen units.
549 *
550 * The two angles describing the arc on a circle are stored into the
551 * <B>second_wx</B> for the starting angle and <B>second_wy</B> for the ending angle.
552 * These angles are expressed in degrees.
553 *
554 * \param [in] w_current The GschemToplevel object.
555 * \param [in] o_current Arc LeptonObject to check.
556 * \param [in] x (unused)
557 * \param [in] y (unused)
558 * \param [out] whichone (unused)
559 */
o_grips_start_arc(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)560 static void o_grips_start_arc(GschemToplevel *w_current, LeptonObject *o_current,
561 int x, int y, int whichone)
562 {
563 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
564
565 /* describe the arc with GschemToplevel variables */
566 /* center */
567 w_current->first_wx = lepton_arc_object_get_center_x (o_current);
568 w_current->first_wy = lepton_arc_object_get_center_y (o_current);
569 /* radius */
570 w_current->distance = lepton_arc_object_get_radius (o_current);
571 /* angles */
572 w_current->second_wx = lepton_arc_object_get_start_angle (o_current);
573 w_current->second_wy = lepton_arc_object_get_sweep_angle (o_current);
574
575 /* draw the first temporary arc */
576 /* o_arc_invalidate_rubber (w_current); */
577 w_current->rubber_visible = 1;
578 }
579
580 /*! \brief Initialize grip motion process for a box.
581 * \par Function Description
582 * This function initializes the grip motion process for a box. From the
583 * <B>o_current</B> pointed object, it stores into the GschemToplevel
584 * structure the .... These variables are used in the grip process.
585 *
586 * The function first erases the grips.
587 *
588 * The coordinates of the selected corner are put in
589 * (<B>w_current->second_wx</B>,<B>w_current->second_wx</B>).
590 *
591 * The coordinates of the opposite corner go in
592 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
593 * to change during the action.
594 *
595 * \param [in] w_current The GschemToplevel object.
596 * \param [in] o_current Box LeptonObject to check.
597 * \param [in] x (unused)
598 * \param [in] y (unused)
599 * \param [out] whichone Which coordinate to check.
600 */
o_grips_start_box(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)601 static void o_grips_start_box(GschemToplevel *w_current, LeptonObject *o_current,
602 int x, int y, int whichone)
603 {
604 int upper_x, upper_y, lower_x, lower_y;
605
606 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
607
608 upper_x = lepton_box_object_get_upper_x (o_current);
609 upper_y = lepton_box_object_get_upper_y (o_current);
610 lower_x = lepton_box_object_get_lower_x (o_current);
611 lower_y = lepton_box_object_get_lower_y (o_current);
612
613 /* (second_wx, second_wy) is the selected corner */
614 /* (first_wx, first_wy) is the opposite corner */
615 switch(whichone) {
616 case BOX_UPPER_LEFT:
617 w_current->second_wx = upper_x;
618 w_current->second_wy = upper_y;
619 w_current->first_wx = lower_x;
620 w_current->first_wy = lower_y;
621 break;
622 case BOX_LOWER_RIGHT:
623 w_current->second_wx = lower_x;
624 w_current->second_wy = lower_y;
625 w_current->first_wx = upper_x;
626 w_current->first_wy = upper_y;
627 break;
628 case BOX_UPPER_RIGHT:
629 w_current->second_wx = lower_x;
630 w_current->second_wy = upper_y;
631 w_current->first_wx = upper_x;
632 w_current->first_wy = lower_y;
633 break;
634 case BOX_LOWER_LEFT:
635 w_current->second_wx = upper_x;
636 w_current->second_wy = lower_y;
637 w_current->first_wx = lower_x;
638 w_current->first_wy = upper_y;
639 break;
640 default:
641 return; /* error */
642 }
643
644 /* draw the first temporary box */
645 /* o_box_invalidate_rubber (w_current); */
646 w_current->rubber_visible = 1;
647 }
648
649 /*! \brief Initialize grip motion process for a path.
650 * \par Function Description
651 * This function initializes the grip motion process for a path.
652 * From the <B>o_current</B> pointed object, it stores into the
653 * GschemToplevel structure the ....
654 * These variables are used in the grip process.
655 *
656 * The function first erases the grips.
657 *
658 * The coordinates of the selected corner are put in
659 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
660 *
661 * The coordinates of the opposite corner go in
662 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
663 * suppose to change during the action.
664 *
665 * \param [in] w_current The GschemToplevel object.
666 * \param [in] o_current Picture LeptonObject to check.
667 * \param [in] x (unused)
668 * \param [in] y (unused)
669 * \param [out] whichone Which coordinate to check.
670 */
o_grips_start_path(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)671 static void o_grips_start_path(GschemToplevel *w_current, LeptonObject *o_current,
672 int x, int y, int whichone)
673 {
674 LeptonPathSection *section;
675 int i;
676 int grip_no = 0;
677 int gx = -1;
678 int gy = -1;
679
680 w_current->last_drawb_mode = -1;
681
682 for (i = 0; i < lepton_path_object_get_num_sections (o_current); i++)
683 {
684 section = lepton_path_object_get_section (o_current, i);
685
686 switch (section->code) {
687 case PATH_CURVETO:
688 /* Two control point grips */
689 if (whichone == grip_no++) {
690 gx = section->x1;
691 gy = section->y1;
692 }
693 if (whichone == grip_no++) {
694 gx = section->x2;
695 gy = section->y2;
696 }
697 /* Fall through */
698 case PATH_MOVETO:
699 case PATH_MOVETO_OPEN:
700 case PATH_LINETO:
701 /* Destination point grip */
702 if (whichone == grip_no++) {
703 gx = section->x3;
704 gy = section->y3;
705 }
706 break;
707 case PATH_END:
708 break;
709 }
710 }
711
712 w_current->first_wx = w_current->second_wx = gx;
713 w_current->first_wy = w_current->second_wy = gy;
714
715 /* draw the first temporary path */
716 /* o_path_invalidate_rubber_grips (w_current); */
717 w_current->rubber_visible = 1;
718 }
719
720 /*! \brief Initialize grip motion process for a picture.
721 * \par Function Description
722 * This function initializes the grip motion process for a picture.
723 * From the <B>o_current</B> pointed object, it stores into the
724 * GschemToplevel structure the ....
725 * These variables are used in the grip process.
726 *
727 * The function first erases the grips.
728 *
729 * The coordinates of the selected corner are put in
730 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
731 *
732 * The coordinates of the opposite corner go in
733 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
734 * suppose to change during the action.
735 *
736 * \param [in] w_current The GschemToplevel object.
737 * \param [in] o_current Picture LeptonObject to check.
738 * \param [in] x (unused)
739 * \param [in] y (unused)
740 * \param [out] whichone Which coordinate to check.
741 */
o_grips_start_picture(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)742 static void o_grips_start_picture(GschemToplevel *w_current, LeptonObject *o_current,
743 int x, int y, int whichone)
744 {
745 int lower_x, lower_y, upper_x, upper_y;
746
747 lower_x = lepton_picture_object_get_lower_x (o_current);
748 lower_y = lepton_picture_object_get_lower_y (o_current);
749 upper_x = lepton_picture_object_get_upper_x (o_current);
750 upper_y = lepton_picture_object_get_upper_y (o_current);
751
752 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
753
754 w_current->current_pixbuf = lepton_picture_object_get_pixbuf (o_current);
755 w_current->pixbuf_filename =
756 g_strdup (lepton_picture_object_get_filename (o_current));
757 w_current->pixbuf_wh_ratio = lepton_picture_object_get_real_ratio (o_current);
758
759 /* (second_wx,second_wy) is the selected corner */
760 /* (first_wx, first_wy) is the opposite corner */
761 switch(whichone) {
762 case PICTURE_UPPER_LEFT:
763 w_current->second_wx = upper_x;
764 w_current->second_wy = upper_y;
765 w_current->first_wx = lower_x;
766 w_current->first_wy = lower_y;
767 break;
768 case PICTURE_LOWER_RIGHT:
769 w_current->second_wx = lower_x;
770 w_current->second_wy = lower_y;
771 w_current->first_wx = upper_x;
772 w_current->first_wy = upper_y;
773 break;
774 case PICTURE_UPPER_RIGHT:
775 w_current->second_wx = lower_x;
776 w_current->second_wy = upper_y;
777 w_current->first_wx = upper_x;
778 w_current->first_wy = lower_y;
779 break;
780 case PICTURE_LOWER_LEFT:
781 w_current->second_wx = upper_x;
782 w_current->second_wy = lower_y;
783 w_current->first_wx = lower_x;
784 w_current->first_wy = upper_y;
785 break;
786 default:
787 return; /* error */
788 }
789
790 /* draw the first temporary picture */
791 /* o_picture_invalidate_rubber (w_current); */
792 w_current->rubber_visible = 1;
793 }
794
795 /*! \brief Initialize grip motion process for a circle.
796 * \par Function Description
797 * This function initializes the grip motion process for a circle.
798 * From the <B>o_current</B> pointed object, it stores into the
799 * GschemToplevel structure the coordinate of the center and the radius.
800 * These variables are used in the grip process.
801 *
802 * The function first erases the grips.
803 *
804 * The coordinates of the center are put in
805 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
806 * to change during the action.
807 *
808 * The radius of the circle is stored in <B>w_current->distance</B>.
809 *
810 * \param [in] w_current The GschemToplevel object.
811 * \param [in] o_current Circle LeptonObject to check.
812 * \param [in] x (unused)
813 * \param [in] y (unused)
814 * \param [out] whichone Which coordinate to check.
815 */
o_grips_start_circle(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)816 static void o_grips_start_circle(GschemToplevel *w_current, LeptonObject *o_current,
817 int x, int y, int whichone)
818 {
819
820 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
821
822 /* store circle center and radius in GschemToplevel structure */
823 w_current->first_wx = lepton_circle_object_get_center_x (o_current);
824 w_current->first_wy = lepton_circle_object_get_center_y (o_current);
825 w_current->distance = lepton_circle_object_get_radius (o_current);
826
827 /* draw the first temporary circle */
828 /* o_circle_invalidate_rubber (w_current); */
829 w_current->rubber_visible = 1;
830 }
831
832 /*! \brief Initialize grip motion process for a line.
833 * This function starts the move of one of the two grips of the line
834 * object <B>o_current</B>.
835 *
836 * During the move of the grip, the line is described by
837 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and
838 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
839 *
840 * The line end that corresponds to the moving grip is in
841 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
842 *
843 * \param [in] w_current The GschemToplevel object.
844 * \param [in] o_current Line LeptonObject to check.
845 * \param [in] x (unused)
846 * \param [in] y (unused)
847 * \param [out] whichone Which coordinate to check.
848 */
o_grips_start_line(GschemToplevel * w_current,LeptonObject * o_current,int x,int y,int whichone)849 static void o_grips_start_line(GschemToplevel *w_current, LeptonObject *o_current,
850 int x, int y, int whichone)
851 {
852 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
853
854 /* describe the line with GschemToplevel variables */
855 w_current->second_wx = o_current->line->x[whichone];
856 w_current->second_wy = o_current->line->y[whichone];
857 w_current->first_wx = o_current->line->x[!whichone];
858 w_current->first_wy = o_current->line->y[!whichone];
859
860 /* draw the first temporary line */
861 /* o_line_invalidate_rubber (w_current); */
862 w_current->rubber_visible = 1;
863 }
864
865 /*! \brief Start process of modifiying one grip.
866 * \par Function Description
867 * This function starts the process of modifying one grip of an object
868 * on the current sheet. The event occured in (<B>w_x</B>,<B>w_y</B>) in world unit.
869 * If this position is related to a grip of an object, the function
870 * prepares the modification of this grip thanks to the user input.
871 *
872 * The function does nothing if an error occured or if no grip
873 * have been found under (<B>w_x</B>,<B>w_y</B>). Otherwise, it
874 * switches the GRIPS mode on if a grip has been found and
875 * modification of the object has been started.
876 *
877 * If a grip has been found, this function modifies the GschemToplevel
878 * variables <B>which_grip</B> and <B>which_object</B> with the identifier
879 * of the grip and the object it belongs to respectively.
880 *
881 * If the \a draw-grips rc setting is "disabled", no grids are
882 * displayed though the object is modified the same way.
883 *
884 * \param [in] w_current The GschemToplevel object.
885 * \param [in] w_x Current x coordinate of pointer in world units.
886 * \param [in] w_y Current y coordinate of pointer in world units.
887 */
o_grips_start(GschemToplevel * w_current,int w_x,int w_y)888 void o_grips_start(GschemToplevel *w_current, int w_x, int w_y)
889 {
890 LeptonObject *object;
891 int whichone;
892 void (*func) (GschemToplevel*, LeptonObject*, int, int, int) = NULL;
893
894 /* search if there is a grip on a selected object at (w_x,w_y) */
895 object = o_grips_search_world(w_current, w_x, w_y, &whichone);
896
897 if (object != NULL) {
898 w_current->which_grip = whichone;
899 w_current->which_object = object;
900
901 /* Switch off drawing for the object being modified */
902 object->dont_redraw = TRUE;
903 o_invalidate (w_current, object);
904
905 /* there is one */
906 /* depending on its type, start the modification process */
907 switch (lepton_object_get_type (object)) {
908 case OBJ_ARC: func = o_grips_start_arc; break;
909 case OBJ_BOX: func = o_grips_start_box; break;
910 case OBJ_PATH: func = o_grips_start_path; break;
911 case OBJ_PICTURE: func = o_grips_start_picture; break;
912 case OBJ_CIRCLE: func = o_grips_start_circle; break;
913 case OBJ_LINE:
914 case OBJ_NET:
915 case OBJ_PIN:
916 case OBJ_BUS: func = o_grips_start_line; break;
917
918 default: break;
919 }
920
921 /* start the modification of a grip on the object */
922 if (func != NULL) {
923 (*func) (w_current, object, w_x, w_y, whichone);
924 i_set_state (w_current, GRIPS);
925 i_action_start (w_current);
926 }
927 }
928 }
929
930 /*! \brief Modify previously selected object according to mouse position.
931 * \par Function Description
932 * This function modify the previously selected
933 * object according to the mouse position in <B>w_x</B> and <B>w_y</B>.
934 * The grip under modification is updated and the temporary object displayed.
935 *
936 * The object under modification is <B>w_current->which_object</B> and
937 * the grip concerned is <B>w_current->which_grip</B>.
938 *
939 * Depending on the object type, a specific function is used.
940 * It erases the temporary object, updates its internal representation,
941 * and draws it again.
942 *
943 * \param [in] w_current The GschemToplevel object.
944 * \param [in] w_x Current x coordinate of pointer in world units.
945 * \param [in] w_y Current y coordinate of pointer in world units.
946 */
o_grips_motion(GschemToplevel * w_current,int w_x,int w_y)947 void o_grips_motion(GschemToplevel *w_current, int w_x, int w_y)
948 {
949 int grip = w_current->which_grip;
950
951 g_assert( w_current->inside_action != 0 );
952 g_return_if_fail( w_current->which_object != NULL );
953
954 switch (lepton_object_get_type (w_current->which_object)) {
955 case OBJ_ARC:
956 o_arc_motion (w_current, w_x, w_y, grip);
957 break;
958
959 case OBJ_BOX:
960 o_box_motion (w_current, w_x, w_y);
961 break;
962
963 case OBJ_PATH:
964 o_path_motion_grips (w_current, w_x, w_y);
965 break;
966
967 case OBJ_PICTURE:
968 o_picture_motion (w_current, w_x, w_y);
969 break;
970
971 case OBJ_CIRCLE:
972 o_circle_motion (w_current, w_x, w_y);
973 break;
974
975 case OBJ_LINE:
976 case OBJ_NET:
977 case OBJ_PIN:
978 case OBJ_BUS:
979 o_line_motion (w_current, w_x, w_y);
980 break;
981
982 default:
983 return; /* error condition */
984 }
985 }
986
987
988 /*! \brief Cancel process of modifying object with grip.
989 *
990 * \par Function Description
991 * This function cancels the process of modifying a parameter
992 * of an object with a grip. It's main utility is to reset the
993 * dont_redraw flag on the object which was being modified.
994 *
995 * \param [in,out] w_current The GschemToplevel object.
996 */
o_grips_cancel(GschemToplevel * w_current)997 void o_grips_cancel(GschemToplevel *w_current)
998 {
999 LeptonObject *object = w_current->which_object;
1000
1001 /* reset global variables */
1002 w_current->which_grip = -1;
1003 w_current->which_object = NULL;
1004 w_current->rubber_visible = 0;
1005
1006 /* Switch drawing of the object back on */
1007 g_return_if_fail (object != NULL);
1008 object->dont_redraw = FALSE;
1009 }
1010
1011
1012 /*! \brief End process of modifying arc object with grip.
1013 * \par Function Description
1014 * This function ends the grips process specific to an arc object. It erases
1015 * the old arc and write back to the object the new parameters of the arc.
1016 * Depending on the grip selected and moved, the right fields are updated.
1017 * The function handles the conversion from screen unit to world unit before
1018 * updating and redrawing.
1019 *
1020 * If the grip at the center of the arc has been moved - modifying the radius
1021 * of the arc -, the new radius is calculated expressed in world unit
1022 * (the center is unchanged). It is updated with the function
1023 * #lepton_arc_object_modify().
1024 *
1025 * If one of the end of arc grip has been moved - modifying one of the
1026 * angles describing the arc -, this angle is updated with the
1027 * #lepton_arc_object_modify() function.
1028 *
1029 * \param [in] w_current The GschemToplevel object.
1030 * \param [in] o_current Arc LeptonObject to end modification on.
1031 * \param [in] whichone Which grip is pointed to.
1032 */
o_grips_end_arc(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1033 static void o_grips_end_arc(GschemToplevel *w_current, LeptonObject *o_current,
1034 int whichone)
1035 {
1036 int arg1, arg2;
1037
1038 /* erase the temporary arc */
1039 /* o_arc_invalidate_rubber (w_current); */
1040
1041 /* determination of the parameters to give to o_arc_modify() */
1042 switch(whichone) {
1043 case ARC_RADIUS:
1044 /* get the radius from w_current */
1045 arg1 = w_current->distance;
1046 /* second parameter is not used */
1047 arg2 = -1;
1048 break;
1049
1050 case ARC_START_ANGLE:
1051 /* get the start angle from w_current */
1052 arg1 = w_current->second_wx;
1053 /* second parameter is not used */
1054 arg2 = -1;
1055 break;
1056
1057 case ARC_SWEEP_ANGLE:
1058 /* get the end angle from w_current */
1059 arg1 = w_current->second_wy;
1060 /* second parameter is not used */
1061 arg2 = -1;
1062 break;
1063
1064 default:
1065 return;
1066 }
1067
1068 /* modify the arc with the parameters determined above */
1069 lepton_arc_object_modify (o_current, arg1, arg2, whichone);
1070 }
1071
1072 /*! \todo Finish function documentation!!!
1073 * \brief End process of modifying box object with grip.
1074 * \par Function Description
1075 *
1076 * \param [in] w_current The GschemToplevel object.
1077 * \param [in] o_current Box LeptonObject to end modification on.
1078 * \param [in] whichone Which grip is pointed to.
1079 */
o_grips_end_box(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1080 static void o_grips_end_box(GschemToplevel *w_current, LeptonObject *o_current,
1081 int whichone)
1082 {
1083 int box_width, box_height;
1084
1085 box_width = GET_BOX_WIDTH (w_current);
1086 box_height = GET_BOX_HEIGHT(w_current);
1087
1088 /* don't allow zero width/height boxes
1089 * this ends the box drawing behavior
1090 * we want this? hack */
1091 if ((box_width == 0) || (box_height == 0)) {
1092 o_box_invalidate_rubber (w_current);
1093 o_invalidate (w_current, o_current);
1094 return;
1095 }
1096
1097 lepton_box_object_modify (o_current, w_current->second_wx, w_current->second_wy, whichone);
1098 }
1099
1100 /*! \todo Finish function documentation!!!
1101 * \brief End process of modifying path object with grip.
1102 * \par Function Description
1103 *
1104 * \param [in] w_current The GschemToplevel object.
1105 * \param [in] o_current Picture LeptonObject to end modification on.
1106 * \param [in] whichone Which grip is pointed to.
1107 */
o_grips_end_path(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1108 static void o_grips_end_path(GschemToplevel *w_current, LeptonObject *o_current,
1109 int whichone)
1110 {
1111 lepton_path_object_modify (o_current,
1112 w_current->second_wx,
1113 w_current->second_wy,
1114 whichone);
1115 }
1116
1117 /*! \todo Finish function documentation!!!
1118 * \brief End process of modifying picture object with grip.
1119 * \par Function Description
1120 *
1121 * \param [in] w_current The GschemToplevel object.
1122 * \param [in] o_current Picture LeptonObject to end modification on.
1123 * \param [in] whichone Which grip is pointed to.
1124 */
o_grips_end_picture(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1125 static void o_grips_end_picture(GschemToplevel *w_current, LeptonObject *o_current,
1126 int whichone)
1127 {
1128 /* don't allow zero width/height pictures
1129 * this ends the picture drawing behavior
1130 * we want this? hack */
1131 if ((GET_PICTURE_WIDTH(w_current) == 0) || (GET_PICTURE_HEIGHT(w_current) == 0)) {
1132 o_picture_invalidate_rubber (w_current);
1133 o_invalidate (w_current, o_current);
1134 return;
1135 }
1136
1137 lepton_picture_object_modify (o_current,
1138 w_current->second_wx,
1139 w_current->second_wy,
1140 whichone);
1141
1142 g_object_unref (w_current->current_pixbuf);
1143 w_current->current_pixbuf = NULL;
1144 g_free (w_current->pixbuf_filename);
1145 w_current->pixbuf_filename = NULL;
1146 w_current->pixbuf_wh_ratio = 0;
1147 }
1148
1149 /*! \brief End process of modifying circle object with grip.
1150 * \par Function Description
1151 * This function ends the process of modifying the radius of the circle
1152 * object <B>*o_current</B>.
1153 * The modified circle is finally normally drawn.
1154 *
1155 * A circle with a null radius is not allowed. In this case, the process
1156 * is stopped and the circle is left unchanged.
1157 *
1158 * The last value of the radius is in <B>w_current->distance</B> in screen units.
1159 *
1160 * \param [in] w_current The GschemToplevel object.
1161 * \param [in] o_current Circle LeptonObject to end modification on.
1162 * \param [in] whichone Which grip is pointed to.
1163 */
o_grips_end_circle(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1164 static void o_grips_end_circle(GschemToplevel *w_current, LeptonObject *o_current,
1165 int whichone)
1166 {
1167 /* don't allow zero radius circles
1168 * this ends the circle drawing behavior
1169 * we want this? hack */
1170 if (w_current->distance == 0) {
1171 o_circle_invalidate_rubber (w_current);
1172 o_invalidate (w_current, o_current);
1173 return;
1174 }
1175
1176 /* modify the radius of the circle */
1177 lepton_circle_object_modify (o_current, w_current->distance, -1, CIRCLE_RADIUS);
1178 }
1179
1180 /*! \brief End process of modifying line object with grip.
1181 * \par Function Description
1182 * This function ends the process of modifying one end of the line
1183 * object <B>*o_current</B>.
1184 * This end is identified by <B>whichone</B>. The line object is modified
1185 * according to the <B>whichone</B> parameter and the last position of the
1186 * line end.
1187 * The modified line is finally normally drawn.
1188 *
1189 * A line with a null width, i.e. when both ends are identical, is not
1190 * allowed. In this case, the process is stopped and the line unchanged.
1191 *
1192 * \param [in] w_current The GschemToplevel object.
1193 * \param [in] o_current Line LeptonObject to end modification on.
1194 * \param [in] whichone Which grip is pointed to.
1195 */
o_grips_end_line(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1196 static void o_grips_end_line(GschemToplevel *w_current, LeptonObject *o_current,
1197 int whichone)
1198 {
1199 /* don't allow zero length nets / lines / pins
1200 * this ends the net drawing behavior
1201 * we want this? hack */
1202 if ((w_current->first_wx == w_current->second_wx) &&
1203 (w_current->first_wy == w_current->second_wy)) {
1204 o_box_invalidate_rubber (w_current);
1205 o_invalidate (w_current, o_current);
1206 return;
1207 }
1208
1209 /* modify the right line end according to whichone */
1210 lepton_line_object_modify (o_current,
1211 w_current->second_wx, w_current->second_wy, whichone);
1212 }
1213
1214
1215 /*! \brief End process of modifying net object with grip.
1216 * \par Function Description
1217 * This function ends the process of modifying one end of the net
1218 * object <B>*o_current</B>.
1219 * This end is identified by <B>whichone</B>. The line object is modified
1220 * according to the <B>whichone</B> parameter and the last position of the
1221 * line end.
1222 * The connections to the modified net are checked and recreated if neccessary.
1223 *
1224 * A net with zero length, i.e. when both ends are identical, is not
1225 * allowed. In this case, the process is stopped and the line unchanged.
1226 *
1227 * \param [in] w_current The GschemToplevel object.
1228 * \param [in] o_current Net LeptonObject to end modification on.
1229 * \param [in] whichone Which grip is pointed to.
1230 */
o_grips_end_net(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1231 static void o_grips_end_net(GschemToplevel *w_current, LeptonObject *o_current,
1232 int whichone)
1233 {
1234 GList *connected_objects;
1235
1236 /* don't allow zero length net
1237 * this ends the net drawing behavior
1238 * we want this? hack */
1239 if ((w_current->first_wx == w_current->second_wx) &&
1240 (w_current->first_wy == w_current->second_wy)) {
1241 o_invalidate (w_current, o_current);
1242 return;
1243 }
1244
1245 s_conn_remove_object_connections (o_current);
1246 lepton_net_object_modify (o_current, w_current->second_wx,
1247 w_current->second_wy, w_current->which_grip);
1248 s_conn_update_object (o_current->page, o_current);
1249
1250 /* add bus rippers if necessary */
1251 connected_objects = s_conn_return_others (NULL, o_current);
1252 o_net_add_busrippers (w_current, o_current, connected_objects);
1253 g_list_free (connected_objects);
1254 }
1255
1256 /*! \brief End process of modifying pin object with grip.
1257 * \par Function Description
1258 * This function ends the process of modifying one end of the pin
1259 * object <B>*o_current</B>.
1260 * This end is identified by <B>whichone</B>. The pin object is modified
1261 * according to the <B>whichone</B> parameter and the last position of the
1262 * pin end.
1263 * The connections to the modified pin are checked and recreated if neccessary.
1264 *
1265 * A pin with zero length, i.e. when both ends are identical, is not
1266 * allowed. In this case, the process is stopped and the line unchanged.
1267 *
1268 * \param [in] w_current The GschemToplevel object.
1269 * \param [in] o_current Net LeptonObject to end modification on.
1270 * \param [in] whichone Which grip is pointed to.
1271 */
o_grips_end_pin(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1272 static void o_grips_end_pin(GschemToplevel *w_current, LeptonObject *o_current,
1273 int whichone)
1274 {
1275 /* don't allow zero length pin
1276 * this ends the pin changing behavior
1277 * we want this? hack */
1278 if ((w_current->first_wx == w_current->second_wx) &&
1279 (w_current->first_wy == w_current->second_wy)) {
1280 o_invalidate (w_current, o_current);
1281 return;
1282 }
1283
1284 s_conn_remove_object_connections (o_current);
1285 lepton_pin_object_modify (o_current,
1286 w_current->second_wx,
1287 w_current->second_wy,
1288 w_current->which_grip);
1289 s_conn_update_object (o_current->page, o_current);
1290 }
1291
1292 /*! \brief End process of modifying bus object with grip.
1293 * \par Function Description
1294 * This function ends the process of modifying one end of the bus
1295 * object <B>*o_current</B>.
1296 * This end is identified by <B>whichone</B>. The line object is modified
1297 * according to the <B>whichone</B> parameter and the last position of the
1298 * bus end.
1299 * The connections to the modified bus are checked and recreated if neccessary.
1300 *
1301 * A bus with zero length, i.e. when both ends are identical, is not
1302 * allowed. In this case, the process is stopped and the bus unchanged.
1303 *
1304 * \param [in] w_current The GschemToplevel object.
1305 * \param [in] o_current bus LeptonObject to end modification on.
1306 * \param [in] whichone Which grip is pointed to.
1307 */
o_grips_end_bus(GschemToplevel * w_current,LeptonObject * o_current,int whichone)1308 static void o_grips_end_bus(GschemToplevel *w_current, LeptonObject *o_current,
1309 int whichone)
1310 {
1311 /* don't allow zero length bus
1312 * this ends the bus changing behavior
1313 * we want this? hack */
1314 if ((w_current->first_wx == w_current->second_wx) &&
1315 (w_current->first_wy == w_current->second_wy)) {
1316 o_invalidate (w_current, o_current);
1317 return;
1318 }
1319
1320 s_conn_remove_object_connections (o_current);
1321 lepton_bus_object_modify (o_current, w_current->second_wx,
1322 w_current->second_wy, w_current->which_grip);
1323 s_conn_update_object (o_current->page, o_current);
1324 }
1325
1326
1327 /*! \brief End process of modifying object with grip.
1328 * \par Function Description
1329 * This function ends the process of modifying a parameter of an object
1330 * with a grip.
1331 * The temporary representation of the object is erased, the object is
1332 * modified and finally drawn.
1333 *
1334 * The object under modification is <B>w_current->which_object</B> and
1335 * the grip concerned is <B>w_current->which_grip</B>.
1336 *
1337 * Depending on the object type, a specific function is used. It erases
1338 * the temporary object, updates the object and draws the modified object
1339 * normally.
1340 *
1341 * \param [in,out] w_current The GschemToplevel object.
1342 */
o_grips_end(GschemToplevel * w_current)1343 void o_grips_end(GschemToplevel *w_current)
1344 {
1345 LeptonObject *object;
1346 int grip;
1347
1348 g_assert (w_current->inside_action != 0);
1349
1350 object = w_current->which_object;
1351 grip = w_current->which_grip;
1352
1353 if (!object) {
1354 /* actually this is an error condition hack */
1355 i_action_stop (w_current);
1356 i_set_state(w_current, SELECT);
1357 return;
1358 }
1359
1360 switch (lepton_object_get_type (object)) {
1361
1362 case(OBJ_ARC):
1363 /* modify an arc object */
1364 o_grips_end_arc(w_current, object, grip);
1365 break;
1366
1367 case(OBJ_BOX):
1368 /* modify a box object */
1369 o_grips_end_box(w_current, object, grip);
1370 break;
1371
1372 case(OBJ_PATH):
1373 /* modify a path object */
1374 o_grips_end_path(w_current, object, grip);
1375 break;
1376
1377 case(OBJ_PICTURE):
1378 /* modify a picture object */
1379 o_grips_end_picture(w_current, object, grip);
1380 break;
1381
1382 case(OBJ_CIRCLE):
1383 /* modify a circle object */
1384 o_grips_end_circle(w_current, object, grip);
1385 break;
1386
1387 case(OBJ_LINE):
1388 /* modify a line object */
1389 o_grips_end_line(w_current, object, grip);
1390 break;
1391
1392 case(OBJ_NET):
1393 /* modify a net object */
1394 o_grips_end_net(w_current, object, grip);
1395 break;
1396
1397 case(OBJ_PIN):
1398 /* modify a pin object */
1399 o_grips_end_pin(w_current, object, grip);
1400 break;
1401
1402 case(OBJ_BUS):
1403 /* modify a bus object */
1404 o_grips_end_bus(w_current, object, grip);
1405 break;
1406
1407 default:
1408 return;
1409 }
1410
1411 /* Switch drawing of the object back on */
1412 object->dont_redraw = FALSE;
1413 o_invalidate (w_current, object);
1414
1415 /* reset global variables */
1416 w_current->which_grip = -1;
1417 w_current->which_object = NULL;
1418
1419 w_current->rubber_visible = 0;
1420
1421 schematic_window_active_page_changed (w_current);
1422 o_undo_savestate_old(w_current, UNDO_ALL);
1423
1424 i_set_state(w_current, SELECT);
1425 i_action_stop (w_current);
1426 }
1427
1428
1429 /*! \brief Draw objects being grip maniuplated from GschemToplevel object.
1430 *
1431 * \par Function Description
1432 * This function draws the objects being grip manipulated.
1433 *
1434 * \param [in] w_current The GschemToplevel object.
1435 */
o_grips_draw_rubber(GschemToplevel * w_current,EdaRenderer * renderer)1436 void o_grips_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer)
1437 {
1438 g_return_if_fail (w_current->which_object != NULL);
1439
1440 switch (lepton_object_get_type (w_current->which_object)) {
1441 case OBJ_ARC:
1442 o_arc_draw_rubber (w_current, renderer);
1443 break;
1444
1445 case OBJ_BOX:
1446 o_box_draw_rubber (w_current, renderer);
1447 break;
1448
1449 case OBJ_PATH:
1450 o_path_draw_rubber_grips (w_current, renderer);
1451 break;
1452
1453 case OBJ_PICTURE:
1454 o_picture_draw_rubber (w_current, renderer);
1455 break;
1456
1457 case OBJ_CIRCLE:
1458 o_circle_draw_rubber (w_current, renderer);
1459 break;
1460
1461 case OBJ_LINE:
1462 case OBJ_NET:
1463 case OBJ_PIN:
1464 case OBJ_BUS:
1465 o_line_draw_rubber (w_current, renderer);
1466 break;
1467
1468 default:
1469 g_return_if_reached ();
1470 }
1471 }
1472