missing NULL terminator in set_config_x
[geda-gaf.git] / gschem / src / o_grips.c
blobb99e946193bf25d32c3b6804c50244432cfef106
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2020 gEDA Contributors (see ChangeLog for details)
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.
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.
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
20 #include <config.h>
22 #include <stdio.h>
23 #include <math.h>
25 #include "gschem.h"
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)
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
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 selected object are in a list starting at
46 * <B>w_current->toplevel->page_current->selection2_head</B>.
47 * The <B>x</B> and <B>y</B> parameters are in world units.
48 * If the point is inside one grip, a pointer on the object it belongs to is
49 * returned and <B>*whichone</B> is set according to the position of the grip
50 * on the object.
51 * Else, <B>*whichone</B> is unchanged and the function returns <B>NULL</B>.
53 * A specific search function is provided for every kind of graphical object.
54 * The list of selected object is covered : each object is tested with the
55 * appropriate function.
57 * \param [in] w_current The GschemToplevel object.
58 * \param [in] x Current x coordinate of pointer in world units.
59 * \param [in] y Current y coordinate of pointer in world units.
60 * \param [out] whichone Which grip point is selected.
61 * \return Pointer to OBJECT the grip is on, NULL otherwise.
63 OBJECT *o_grips_search_world(GschemToplevel *w_current, int x, int y, int *whichone)
65 OBJECT *object=NULL;
66 OBJECT *found=NULL;
67 GList *s_current;
68 int size;
69 int w_size;
71 GschemPageView *page_view = gschem_toplevel_get_current_page_view (w_current);
72 g_return_val_if_fail (page_view != NULL, NULL);
74 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
75 g_return_val_if_fail (toplevel != NULL, NULL);
78 if (!whichone) {
79 return(NULL);
82 /* get the size of the grip according to zoom level */
83 size = GRIP_SIZE / 2;
84 w_size = gschem_page_view_WORLDabs (page_view, size);
86 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
87 while (s_current != NULL) {
88 object = (OBJECT *) s_current->data;
89 if (object) {
90 switch(object->type) {
91 case(OBJ_ARC):
92 /* check the grips of the arc object */
93 found = o_grips_search_arc_world(w_current, object,
94 x, y, w_size, whichone);
95 if(found != NULL) return found;
96 break;
98 case(OBJ_BOX):
99 /* check the grips of the box object */
100 found = o_grips_search_box_world(w_current, object,
101 x, y, w_size, whichone);
102 if(found != NULL) return found;
103 break;
105 case(OBJ_PATH):
106 /* check the grips of the path object */
107 found = o_grips_search_path_world(w_current, object,
108 x, y, w_size, whichone);
109 if(found != NULL) return found;
110 break;
112 case(OBJ_PICTURE):
113 /* check the grips of the picture object */
114 found = o_grips_search_picture_world(w_current, object,
115 x, y, w_size, whichone);
116 if(found != NULL) return found;
117 break;
119 case(OBJ_CIRCLE):
120 /* check the grips of the circle object */
121 found = o_grips_search_circle_world(w_current, object,
122 x, y, w_size, whichone);
123 if(found != NULL) return found;
124 break;
126 case(OBJ_LINE):
127 case(OBJ_PIN):
128 case(OBJ_NET):
129 case(OBJ_BUS):
130 /* check the grips of the line object */
131 /* the function is the same for line, pin, net, bus */
132 found = o_grips_search_line_world(w_current, object,
133 x, y, w_size, whichone);
134 if(found != NULL) return found;
135 break;
137 default:
138 break;
141 s_current = g_list_next(s_current);
144 return(NULL);
148 /*! \brief Check if pointer is inside the grip region.
150 * \par Function Description
151 * This function checks if the point (<B>x</B>,<B>y</B>) is
152 * inside the grip centered at (<B>grip_x</B>,<B>grip_y</B>).
154 * \param [in] x Current x coordinate of pointer in world units.
155 * \param [in] y Current y coordinate of pointer in world units.
156 * \param [in] grip_x Current x coordinate of grip center in world units.
157 * \param [in] grip_y Current y coordinate of grip center in world units.
158 * \param [in] size Half the width of the grip square in world units.
159 * \return True / False whether the mouse pointer is inside the grip.
161 static gboolean inside_grip( int x, int y, int grip_x, int grip_y, int size )
163 int xmin, ymin, xmax, ymax;
165 xmin = grip_x - size;
166 ymin = grip_y - size;
167 xmax = xmin + 2 * size;
168 ymax = ymin + 2 * size;
170 return inside_region(xmin, ymin, xmax, ymax, x, y);
173 /*! \brief Check if pointer is inside arc grip.
174 * \par Function Description
175 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
176 * inside one of the grips of an <B>o_current</B> pointed arc object. If so
177 * the <B>whichone</B> pointed integer is set to the number of this grip and
178 * the return pointer is a pointer on this object. If the point is not
179 * inside a grip the function returns a NULL pointer and the <B>whichone</B>
180 * pointed integer is unset.
182 * An arc object has three grips :
183 * <DL>
184 * <DT>*</DT><DD>one at the center of the arc. This grip is used to modify
185 * the radius of the arc. If this one is selected, the
186 * <B>whichone</B> pointed integer is set to <B>ARC_RADIUS</B>.
187 * <DT>*</DT><DD>one at one end of the arc. It corresponds to the starting
188 * angle of the arc. If this one is selected, the
189 * <B>whichone</B> pointed integer is set to <B>ARC_START_ANGLE</B>.
190 * <DT>*</DT><DD>one at the other end of the arc. It corresponds to the
191 * ending angle of the arc. If this one is selected, the
192 * <B>whichone</B> pointed integer is set to <B>ARC_SWEEP_ANGLE</B>.
193 * </DL>
195 * The <B>x</B> and <B>y</B> parameters are in world units.
197 * The <B>size</B> parameter is the width (and height) of the square
198 * representing a grip in world units.
200 * \param [in] w_current The GschemToplevel object.
201 * \param [in] o_current Arc OBJECT to check.
202 * \param [in] x Current x coordinate of pointer in world units.
203 * \param [in] y Current y coordinate of pointer in world units.
204 * \param [in] size Half the width of the grip square in world units.
205 * \param [out] whichone Which grip point is selected.
206 * \return Pointer to OBJECT the grip is on, NULL otherwise.
208 OBJECT *o_grips_search_arc_world(GschemToplevel *w_current, OBJECT *o_current,
209 int x, int y, int size, int *whichone)
211 int centerx, centery, radius, start_angle, sweep_angle;
212 double tmp;
214 centerx = o_current->arc->x;
215 centery = o_current->arc->y;
216 radius = o_current->arc->radius;
217 start_angle = o_current->arc->start_angle;
218 sweep_angle = o_current->arc->sweep_angle;
220 /* check the grip on the center of the arc */
221 if (inside_grip(x, y, centerx, centery, size)) {
222 *whichone = ARC_RADIUS;
223 return(o_current);
226 /* check the grip at the end angle of the arc */
227 tmp = ((double) start_angle + sweep_angle) * M_PI / 180;
228 if (inside_grip(x, y,
229 centerx + radius * cos(tmp),
230 centery + radius * sin(tmp), size)) {
231 *whichone = ARC_SWEEP_ANGLE;
232 return(o_current);
235 /* check the grip at the start angle of the arc */
236 tmp = ((double) start_angle) * M_PI / 180;
237 if (inside_grip(x, y,
238 centerx + radius * cos(tmp),
239 centery + radius * sin(tmp), size)) {
240 *whichone = ARC_START_ANGLE;
241 return(o_current);
244 return NULL;
247 /*! \brief Check if pointer is inside box grip.
248 * \par Function Description
249 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
250 * inside one of the grips of the <B>o_current</B> pointed box object.
251 * If so, the <B>whichone</B> pointed integer is set to the identifier of
252 * this grip and the returned pointer is a pointer on this object.
253 * If the point is not inside a grip the function returns a NULL pointer
254 * and the <B>whichone</B> pointed integer is unset.
256 * A box object has four grips : one at each corner of the box. The
257 * identifiers of each corner are <B>BOX_UPPER_LEFT</B>,
258 * <B>BOX_UPPER_RIGHT</B>, <B>BOX_LOWER_LEFT</B> and <B>BOX_LOWER_RIGHT</B>.
260 * The <B>x</B> and <B>y</B> parameters are in world units.
262 * The <B>size</B> parameter is half the width (and half the height) of
263 * the square representing a grip in world units.
265 * \param [in] w_current The GschemToplevel object.
266 * \param [in] o_current Box OBJECT to check.
267 * \param [in] x Current x coordinate of pointer in world units.
268 * \param [in] y Current y coordinate of pointer in world units.
269 * \param [in] size Half the width of the grip square in world units.
270 * \param [out] whichone Which grip point is selected.
271 * \return Pointer to OBJECT the grip is on, NULL otherwise.
273 OBJECT *o_grips_search_box_world(GschemToplevel *w_current, OBJECT *o_current,
274 int x, int y, int size, int *whichone)
276 /* inside upper left grip ? */
277 if (inside_grip(x, y,
278 o_current->box->upper_x,
279 o_current->box->upper_y, size)) {
280 *whichone = BOX_UPPER_LEFT;
281 return(o_current);
284 /* inside lower right grip ? */
285 if (inside_grip(x, y,
286 o_current->box->lower_x,
287 o_current->box->lower_y, size)) {
288 *whichone = BOX_LOWER_RIGHT;
289 return(o_current);
292 /* inside upper right grip ? */
293 if (inside_grip(x, y,
294 o_current->box->lower_x,
295 o_current->box->upper_y, size)) {
296 *whichone = BOX_UPPER_RIGHT;
297 return(o_current);
300 /* inside lower left grip ? */
301 if (inside_grip(x, y,
302 o_current->box->upper_x,
303 o_current->box->lower_y, size)) {
304 *whichone = BOX_LOWER_LEFT;
305 return(o_current);
308 return NULL;
311 /*! \brief Check if pointer is inside path grip.
312 * \par Function Description
313 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>)
314 * is inside one of the grips of the <B>o_current</B> pointed path object.
315 * If so, the <B>whichone</B> pointed integer is set to the identifier of
316 * this grip and the returned pointer is a pointer on this object.
317 * If the point is not inside a grip the function returns a NULL pointer
318 * and the <B>whichone</B> pointed integer is unset.
320 * A path object has four grips : one at each corner of the path.
321 * The identifiers of each corner are #PICTURE_UPPER_LEFT,
322 * #PICTURE_UPPER_RIGHT, #PICTURE_LOWER_LEFT and
323 * #PICTURE_LOWER_RIGHT.
325 * The <B>x</B> and <B>y</B> parameters are in world units.
327 * The <B>size</B> parameter is half the width (and half the height) of the
328 * square representing a grip in world units.
330 * \param [in] w_current The GschemToplevel object.
331 * \param [in] o_current Picture OBJECT to check.
332 * \param [in] x Current x coordinate of pointer in world units.
333 * \param [in] y Current y coordinate of pointer in world units.
334 * \param [in] size Half the width of the grip square in world units.
335 * \param [out] whichone Which grip point is selected.
336 * \return Pointer to OBJECT the grip is on, NULL otherwise.
338 OBJECT *o_grips_search_path_world(GschemToplevel *w_current, OBJECT *o_current,
339 int x, int y, int size, int *whichone)
341 PATH_SECTION *section;
342 int i;
343 int grip_no = 0;
345 for (i = 0; i < o_current->path->num_sections; i++) {
346 section = &o_current->path->sections[i];
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;
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;
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;
371 grip_no ++;
372 break;
373 case PATH_END:
374 break;
378 return NULL;
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.
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.
395 * The <B>x</B> and <B>y</B> parameters are in world units.
397 * The <B>size</B> parameter is half the width (and half the height) of the
398 * square representing a grip in world units.
400 * \param [in] w_current The GschemToplevel object.
401 * \param [in] o_current Picture OBJECT 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 OBJECT the grip is on, NULL otherwise.
408 OBJECT *o_grips_search_picture_world(GschemToplevel *w_current, OBJECT *o_current,
409 int x, int y, int size, int *whichone)
411 /* inside upper left grip ? */
412 if (inside_grip(x, y,
413 o_current->picture->upper_x,
414 o_current->picture->upper_y, size)) {
415 *whichone = PICTURE_UPPER_LEFT;
416 return(o_current);
419 /* inside lower right grip ? */
420 if (inside_grip(x, y,
421 o_current->picture->lower_x,
422 o_current->picture->lower_y, size)) {
423 *whichone = PICTURE_LOWER_RIGHT;
424 return(o_current);
427 /* inside upper right grip ? */
428 if (inside_grip(x, y,
429 o_current->picture->lower_x,
430 o_current->picture->upper_y, size)) {
431 *whichone = PICTURE_UPPER_RIGHT;
432 return(o_current);
435 /* inside lower left grip ? */
436 if (inside_grip(x, y,
437 o_current->picture->upper_x,
438 o_current->picture->lower_y, size)) {
439 *whichone = PICTURE_LOWER_LEFT;
440 return(o_current);
443 return NULL;
446 /*! \brief Check if pointer is inside circle grip.
447 * \par Function Description
448 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
449 * the grip of the circle object <B>o_current</B>.
450 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
451 * is in one of these areas.
452 * If the event occured in one of the grip, a pointer on the object is
453 * returned and <B>*whichone</B> is set to the identifier of the grip.
454 * If not, the function returns a <B>NULL</B> pointer and <B>*whichone</B>
455 * is unchanged.
457 * The parameter <B>size</B> is half the size of the grip in world units.
459 * A circle has only one grip on the lower right corner of the box it
460 * is inscribed in. Moving this grip change the radius of the circle.
461 * The identifier of this grip is <B>CIRCLE_RADIUS</B>.
463 * \param [in] w_current The GschemToplevel object.
464 * \param [in] o_current Circle OBJECT to check.
465 * \param [in] x Current x coordinate of pointer in world units.
466 * \param [in] y Current y coordinate of pointer in world units.
467 * \param [in] size Half the width of the grip square in world units.
468 * \param [out] whichone Which grip point is selected.
469 * \return Pointer to OBJECT the grip is on, NULL otherwise.
471 OBJECT *o_grips_search_circle_world(GschemToplevel *w_current, OBJECT *o_current,
472 int x, int y, int size, int *whichone)
474 /* check the grip for radius */
475 if (inside_grip(x, y,
476 o_current->circle->center_x + o_current->circle->radius,
477 o_current->circle->center_y - o_current->circle->radius,
478 size)) {
479 *whichone = CIRCLE_RADIUS;
480 return(o_current);
483 return NULL;
486 /*! \brief Check if pointer is inside line grip.
487 * \par Function Description
488 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
489 * the grip of the line object <B>o_current</B>.
490 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
491 * is in one of these areas.
492 * If the event occured in one of its grip, a pointer on the object is
493 * returned and <B>*whichone</B> is set to the identifier of the grip. If not,
494 * the function returns <B>NULL</B> pointer and <B>*whichone</B> is unchanged.
496 * The parameter <B>size</B> is half the size of the grip in world units.
498 * \param [in] w_current The GschemToplevel object.
499 * \param [in] o_current Line OBJECT to check.
500 * \param [in] x Current x coordinate of pointer in world units.
501 * \param [in] y Current y coordinate of pointer in world units.
502 * \param [in] size Half the width of the grip square in world units.
503 * \param [out] whichone Which grip point is selected.
504 * \return Pointer to OBJECT the grip is on, NULL otherwise.
506 OBJECT *o_grips_search_line_world(GschemToplevel *w_current, OBJECT *o_current,
507 int x, int y, int size, int *whichone)
509 /* check the grip on the end of line 1 */
510 if (inside_grip(x, y,
511 o_current->line->x[LINE_END1],
512 o_current->line->y[LINE_END1], size)) {
513 *whichone = LINE_END1;
514 return(o_current);
517 /* check the grip on the end of line 2 */
518 if (inside_grip(x, y,
519 o_current->line->x[LINE_END2],
520 o_current->line->y[LINE_END2], size)) {
521 *whichone = LINE_END2;
522 return(o_current);
525 return NULL;
528 /*! \brief Initialize grip motion process for an arc.
529 * \par Function Description
530 * This function initializes the grip motion process for an arc.
531 * From the <B>o_current</B> pointed object, it stores into the
532 * GschemToplevel structure the coordinates of the center, the radius
533 * and the two angle that describes an arc. These variables are used in
534 * the grip process.
536 * The coordinates of the center of the arc on x- and y-axis are stored
537 * into the <B>first_wx</B> and <B>first_wy</B> fields of the GschemToplevel
538 * structure in screen units.
540 * The radius of the center is stored into the <B>distance</B> field of
541 * the GschemToplevel structure in screen units.
543 * The two angles describing the arc on a circle are stored into the
544 * <B>second_wx</B> for the starting angle and <B>second_wy</B> for the ending angle.
545 * These angles are expressed in degrees.
547 * \param [in] w_current The GschemToplevel object.
548 * \param [in] o_current Arc OBJECT to check.
549 * \param [in] x (unused)
550 * \param [in] y (unused)
551 * \param [out] whichone (unused)
553 static void o_grips_start_arc(GschemToplevel *w_current, OBJECT *o_current,
554 int x, int y, int whichone)
556 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
558 /* describe the arc with GschemToplevel variables */
559 /* center */
560 w_current->first_wx = o_current->arc->x;
561 w_current->first_wy = o_current->arc->y;
562 /* radius */
563 w_current->distance = o_current->arc->radius;
564 /* angles */
565 w_current->second_wx = o_current->arc->start_angle;
566 w_current->second_wy = o_current->arc->sweep_angle;
568 /* draw the first temporary arc */
569 /* o_arc_invalidate_rubber (w_current); */
570 w_current->rubber_visible = 1;
573 /*! \brief Initialize grip motion process for a box.
574 * \par Function Description
575 * This function initializes the grip motion process for a box. From the
576 * <B>o_current</B> pointed object, it stores into the GschemToplevel
577 * structure the .... These variables are used in the grip process.
579 * The function first erases the grips.
581 * The coordinates of the selected corner are put in
582 * (<B>w_current->second_wx</B>,<B>w_current->second_wx</B>).
584 * The coordinates of the opposite corner go in
585 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
586 * to change during the action.
588 * \param [in] w_current The GschemToplevel object.
589 * \param [in] o_current Box OBJECT to check.
590 * \param [in] x (unused)
591 * \param [in] y (unused)
592 * \param [out] whichone Which coordinate to check.
594 static void o_grips_start_box(GschemToplevel *w_current, OBJECT *o_current,
595 int x, int y, int whichone)
597 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
599 /* (second_wx, second_wy) is the selected corner */
600 /* (first_wx, first_wy) is the opposite corner */
601 switch(whichone) {
602 case BOX_UPPER_LEFT:
603 w_current->second_wx = o_current->box->upper_x;
604 w_current->second_wy = o_current->box->upper_y;
605 w_current->first_wx = o_current->box->lower_x;
606 w_current->first_wy = o_current->box->lower_y;
607 break;
608 case BOX_LOWER_RIGHT:
609 w_current->second_wx = o_current->box->lower_x;
610 w_current->second_wy = o_current->box->lower_y;
611 w_current->first_wx = o_current->box->upper_x;
612 w_current->first_wy = o_current->box->upper_y;
613 break;
614 case BOX_UPPER_RIGHT:
615 w_current->second_wx = o_current->box->lower_x;
616 w_current->second_wy = o_current->box->upper_y;
617 w_current->first_wx = o_current->box->upper_x;
618 w_current->first_wy = o_current->box->lower_y;
619 break;
620 case BOX_LOWER_LEFT:
621 w_current->second_wx = o_current->box->upper_x;
622 w_current->second_wy = o_current->box->lower_y;
623 w_current->first_wx = o_current->box->lower_x;
624 w_current->first_wy = o_current->box->upper_y;
625 break;
626 default:
627 return; /* error */
630 /* draw the first temporary box */
631 /* o_box_invalidate_rubber (w_current); */
632 w_current->rubber_visible = 1;
635 /*! \brief Initialize grip motion process for a path.
636 * \par Function Description
637 * This function initializes the grip motion process for a path.
638 * From the <B>o_current</B> pointed object, it stores into the
639 * GschemToplevel structure the ....
640 * These variables are used in the grip process.
642 * The function first erases the grips.
644 * The coordinates of the selected corner are put in
645 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
647 * The coordinates of the opposite corner go in
648 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
649 * suppose to change during the action.
651 * \param [in] w_current The GschemToplevel object.
652 * \param [in] o_current Picture OBJECT to check.
653 * \param [in] x (unused)
654 * \param [in] y (unused)
655 * \param [out] whichone Which coordinate to check.
657 static void o_grips_start_path(GschemToplevel *w_current, OBJECT *o_current,
658 int x, int y, int whichone)
660 PATH_SECTION *section;
661 int i;
662 int grip_no = 0;
663 int gx = -1;
664 int gy = -1;
666 w_current->last_drawb_mode = -1;
668 for (i = 0; i < o_current->path->num_sections; i++) {
669 section = &o_current->path->sections[i];
671 switch (section->code) {
672 case PATH_CURVETO:
673 /* Two control point grips */
674 if (whichone == grip_no++) {
675 gx = section->x1;
676 gy = section->y1;
678 if (whichone == grip_no++) {
679 gx = section->x2;
680 gy = section->y2;
682 /* Fall through */
683 case PATH_MOVETO:
684 case PATH_MOVETO_OPEN:
685 case PATH_LINETO:
686 /* Destination point grip */
687 if (whichone == grip_no++) {
688 gx = section->x3;
689 gy = section->y3;
691 break;
692 case PATH_END:
693 break;
697 w_current->first_wx = w_current->second_wx = gx;
698 w_current->first_wy = w_current->second_wy = gy;
700 /* draw the first temporary path */
701 /* o_path_invalidate_rubber_grips (w_current); */
702 w_current->rubber_visible = 1;
705 /*! \brief Initialize grip motion process for a picture.
706 * \par Function Description
707 * This function initializes the grip motion process for a picture.
708 * From the <B>o_current</B> pointed object, it stores into the
709 * GschemToplevel structure the ....
710 * These variables are used in the grip process.
712 * The function first erases the grips.
714 * The coordinates of the selected corner are put in
715 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
717 * The coordinates of the opposite corner go in
718 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
719 * suppose to change during the action.
721 * \param [in] w_current The GschemToplevel object.
722 * \param [in] o_current Picture OBJECT to check.
723 * \param [in] x (unused)
724 * \param [in] y (unused)
725 * \param [out] whichone Which coordinate to check.
727 static void o_grips_start_picture(GschemToplevel *w_current, OBJECT *o_current,
728 int x, int y, int whichone)
730 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
731 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
733 w_current->current_pixbuf = o_picture_get_pixbuf (toplevel, o_current);
734 w_current->pixbuf_filename =
735 g_strdup (o_picture_get_filename (o_current));
736 w_current->pixbuf_wh_ratio = o_picture_get_ratio (toplevel, o_current);
738 /* (second_wx,second_wy) is the selected corner */
739 /* (first_wx, first_wy) is the opposite corner */
740 switch(whichone) {
741 case PICTURE_UPPER_LEFT:
742 w_current->second_wx = o_current->picture->upper_x;
743 w_current->second_wy = o_current->picture->upper_y;
744 w_current->first_wx = o_current->picture->lower_x;
745 w_current->first_wy = o_current->picture->lower_y;
746 break;
747 case PICTURE_LOWER_RIGHT:
748 w_current->second_wx = o_current->picture->lower_x;
749 w_current->second_wy = o_current->picture->lower_y;
750 w_current->first_wx = o_current->picture->upper_x;
751 w_current->first_wy = o_current->picture->upper_y;
752 break;
753 case PICTURE_UPPER_RIGHT:
754 w_current->second_wx = o_current->picture->lower_x;
755 w_current->second_wy = o_current->picture->upper_y;
756 w_current->first_wx = o_current->picture->upper_x;
757 w_current->first_wy = o_current->picture->lower_y;
758 break;
759 case PICTURE_LOWER_LEFT:
760 w_current->second_wx = o_current->picture->upper_x;
761 w_current->second_wy = o_current->picture->lower_y;
762 w_current->first_wx = o_current->picture->lower_x;
763 w_current->first_wy = o_current->picture->upper_y;
764 break;
765 default:
766 return; /* error */
769 /* draw the first temporary picture */
770 /* o_picture_invalidate_rubber (w_current); */
771 w_current->rubber_visible = 1;
774 /*! \brief Initialize grip motion process for a circle.
775 * \par Function Description
776 * This function initializes the grip motion process for a circle.
777 * From the <B>o_current</B> pointed object, it stores into the
778 * GschemToplevel structure the coordinate of the center and the radius.
779 * These variables are used in the grip process.
781 * The function first erases the grips.
783 * The coordinates of the center are put in
784 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
785 * to change during the action.
787 * The radius of the circle is stored in <B>w_current->distance</B>.
789 * \param [in] w_current The GschemToplevel object.
790 * \param [in] o_current Circle OBJECT to check.
791 * \param [in] x (unused)
792 * \param [in] y (unused)
793 * \param [out] whichone Which coordinate to check.
795 static void o_grips_start_circle(GschemToplevel *w_current, OBJECT *o_current,
796 int x, int y, int whichone)
799 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
801 /* store circle center and radius in GschemToplevel structure */
802 w_current->first_wx = o_current->circle->center_x;
803 w_current->first_wy = o_current->circle->center_y;
804 w_current->distance = o_current->circle->radius;
806 /* draw the first temporary circle */
807 /* o_circle_invalidate_rubber (w_current); */
808 w_current->rubber_visible = 1;
811 /*! \brief Initialize grip motion process for a line.
812 * This function starts the move of one of the two grips of the line
813 * object <B>o_current</B>.
815 * During the move of the grip, the line is described by
816 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and
817 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
819 * The line end that corresponds to the moving grip is in
820 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
822 * \param [in] w_current The GschemToplevel object.
823 * \param [in] o_current Line OBJECT to check.
824 * \param [in] x (unused)
825 * \param [in] y (unused)
826 * \param [out] whichone Which coordinate to check.
828 static void o_grips_start_line(GschemToplevel *w_current, OBJECT *o_current,
829 int x, int y, int whichone)
831 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
833 /* describe the line with GschemToplevel variables */
834 w_current->second_wx = o_current->line->x[whichone];
835 w_current->second_wy = o_current->line->y[whichone];
836 w_current->first_wx = o_current->line->x[!whichone];
837 w_current->first_wy = o_current->line->y[!whichone];
839 /* draw the first temporary line */
840 /* o_line_invalidate_rubber (w_current); */
841 w_current->rubber_visible = 1;
844 /*! \brief Start process of modifiying one grip.
845 * \par Function Description
846 * This function starts the process of modifying one grip of an object
847 * on the current sheet. The event occured in (<B>w_x</B>,<B>w_y</B>) in world unit.
848 * If this position is related to a grip of an object, the function
849 * prepares the modification of this grip thanks to the user input.
851 * The function does nothing if an error occured or if no grip
852 * have been found under (<B>w_x</B>,<B>w_y</B>). Otherwise, it
853 * switches the GRIPS mode on if a grip has been found and
854 * modification of the object has been started.
856 * If a grip has been found, this function modifies the GschemToplevel
857 * variables <B>which_grip</B> and <B>which_object</B> with the identifier
858 * of the grip and the object it belongs to respectively.
860 * \param [in] w_current The GschemToplevel object.
861 * \param [in] w_x Current x coordinate of pointer in world units.
862 * \param [in] w_y Current y coordinate of pointer in world units.
864 void o_grips_start(GschemToplevel *w_current, int w_x, int w_y)
866 OBJECT *object;
867 int whichone;
868 void (*func) (GschemToplevel*, OBJECT*, int, int, int) = NULL;
870 if (w_current->draw_grips) {
872 /* search if there is a grip on a selected object at (w_x,w_y) */
873 object = o_grips_search_world(w_current, w_x, w_y, &whichone);
875 if (object != NULL) {
876 w_current->which_grip = whichone;
877 w_current->which_object = object;
879 /* Switch off drawing for the object being modified */
880 object->dont_redraw = TRUE;
881 o_invalidate (w_current, object);
883 /* there is one */
884 /* depending on its type, start the modification process */
885 switch (object->type) {
886 case OBJ_ARC: func = o_grips_start_arc; break;
887 case OBJ_BOX: func = o_grips_start_box; break;
888 case OBJ_PATH: func = o_grips_start_path; break;
889 case OBJ_PICTURE: func = o_grips_start_picture; break;
890 case OBJ_CIRCLE: func = o_grips_start_circle; break;
891 case OBJ_LINE:
892 case OBJ_NET:
893 case OBJ_PIN:
894 case OBJ_BUS: func = o_grips_start_line; break;
896 default: break;
899 /* start the modification of a grip on the object */
900 if (func != NULL) {
901 (*func) (w_current, object, w_x, w_y, whichone);
902 i_set_state (w_current, GRIPS);
903 i_action_start (w_current);
909 /*! \brief Modify previously selected object according to mouse position.
910 * \par Function Description
911 * This function modify the previously selected
912 * object according to the mouse position in <B>w_x</B> and <B>w_y</B>.
913 * The grip under modification is updated and the temporary object displayed.
915 * The object under modification is <B>w_current->which_object</B> and
916 * the grip concerned is <B>w_current->which_grip</B>.
918 * Depending on the object type, a specific function is used.
919 * It erases the temporary object, updates its internal representation,
920 * and draws it again.
922 * \param [in] w_current The GschemToplevel object.
923 * \param [in] w_x Current x coordinate of pointer in world units.
924 * \param [in] w_y Current y coordinate of pointer in world units.
926 void o_grips_motion(GschemToplevel *w_current, int w_x, int w_y)
928 int grip = w_current->which_grip;
930 g_assert( w_current->inside_action != 0 );
931 g_return_if_fail( w_current->which_object != NULL );
933 switch(w_current->which_object->type) {
934 case OBJ_ARC:
935 o_arc_motion (w_current, w_x, w_y, grip);
936 break;
938 case OBJ_BOX:
939 o_box_motion (w_current, w_x, w_y);
940 break;
942 case OBJ_PATH:
943 o_path_motion_grips (w_current, w_x, w_y);
944 break;
946 case OBJ_PICTURE:
947 o_picture_motion (w_current, w_x, w_y);
948 break;
950 case OBJ_CIRCLE:
951 o_circle_motion (w_current, w_x, w_y);
952 break;
954 case OBJ_LINE:
955 case OBJ_NET:
956 case OBJ_PIN:
957 case OBJ_BUS:
958 o_line_motion (w_current, w_x, w_y);
959 break;
961 default:
962 return; /* error condition */
967 /*! \brief Cancel process of modifying object with grip.
969 * \par Function Description
970 * This function cancels the process of modifying a parameter
971 * of an object with a grip. It's main utility is to reset the
972 * dont_redraw flag on the object which was being modified.
974 * \param [in,out] w_current The GschemToplevel object.
976 void o_grips_cancel(GschemToplevel *w_current)
978 OBJECT *object = w_current->which_object;
980 /* reset global variables */
981 w_current->which_grip = -1;
982 w_current->which_object = NULL;
983 w_current->rubber_visible = 0;
985 /* Switch drawing of the object back on */
986 g_return_if_fail (object != NULL);
987 object->dont_redraw = FALSE;
991 /*! \brief End process of modifying arc object with grip.
992 * \par Function Description
993 * This function ends the grips process specific to an arc object. It erases
994 * the old arc and write back to the object the new parameters of the arc.
995 * Depending on the grip selected and moved, the right fields are updated.
996 * The function handles the conversion from screen unit to world unit before
997 * updating and redrawing.
999 * If the grip at the center of the arc has been moved - modifying the radius
1000 * of the arc -, the new radius is calculated expressed in world unit
1001 * (the center is unchanged). It is updated with the function #o_arc_modify().
1003 * If one of the end of arc grip has been moved - modifying one of the
1004 * angles describing the arc -, this angle is updated with the
1005 * #o_arc_modify() function.
1007 * \param [in] w_current The GschemToplevel object.
1008 * \param [in] o_current Arc OBJECT to end modification on.
1009 * \param [in] whichone Which grip is pointed to.
1011 static void o_grips_end_arc(GschemToplevel *w_current, OBJECT *o_current,
1012 int whichone)
1014 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1015 int arg1, arg2;
1017 /* erase the temporary arc */
1018 /* o_arc_invalidate_rubber (w_current); */
1020 /* determination of the parameters to give to o_arc_modify() */
1021 switch(whichone) {
1022 case ARC_RADIUS:
1023 /* get the radius from w_current */
1024 arg1 = w_current->distance;
1025 /* second parameter is not used */
1026 arg2 = -1;
1027 break;
1029 case ARC_START_ANGLE:
1030 /* get the start angle from w_current */
1031 arg1 = w_current->second_wx;
1032 /* second parameter is not used */
1033 arg2 = -1;
1034 break;
1036 case ARC_SWEEP_ANGLE:
1037 /* get the end angle from w_current */
1038 arg1 = w_current->second_wy;
1039 /* second parameter is not used */
1040 arg2 = -1;
1041 break;
1043 default:
1044 return;
1047 /* modify the arc with the parameters determined above */
1048 o_arc_modify(toplevel, o_current, arg1, arg2, whichone);
1051 /*! \todo Finish function documentation!!!
1052 * \brief End process of modifying box object with grip.
1053 * \par Function Description
1055 * \param [in] w_current The GschemToplevel object.
1056 * \param [in] o_current Box OBJECT to end modification on.
1057 * \param [in] whichone Which grip is pointed to.
1059 static void o_grips_end_box(GschemToplevel *w_current, OBJECT *o_current,
1060 int whichone)
1062 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1063 int box_width, box_height;
1065 box_width = GET_BOX_WIDTH (w_current);
1066 box_height = GET_BOX_HEIGHT(w_current);
1068 /* don't allow zero width/height boxes
1069 * this ends the box drawing behavior
1070 * we want this? hack */
1071 if ((box_width == 0) || (box_height == 0)) {
1072 o_box_invalidate_rubber (w_current);
1073 o_invalidate (w_current, o_current);
1074 return;
1077 o_box_modify(toplevel, o_current, w_current->second_wx, w_current->second_wy, whichone);
1080 /*! \todo Finish function documentation!!!
1081 * \brief End process of modifying path object with grip.
1082 * \par Function Description
1084 * \param [in] w_current The GschemToplevel object.
1085 * \param [in] o_current Picture OBJECT to end modification on.
1086 * \param [in] whichone Which grip is pointed to.
1088 static void o_grips_end_path(GschemToplevel *w_current, OBJECT *o_current,
1089 int whichone)
1091 o_path_modify (w_current->toplevel, o_current,
1092 w_current->second_wx, w_current->second_wy, whichone);
1095 /*! \todo Finish function documentation!!!
1096 * \brief End process of modifying picture object with grip.
1097 * \par Function Description
1099 * \param [in] w_current The GschemToplevel object.
1100 * \param [in] o_current Picture OBJECT to end modification on.
1101 * \param [in] whichone Which grip is pointed to.
1103 static void o_grips_end_picture(GschemToplevel *w_current, OBJECT *o_current,
1104 int whichone)
1106 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1108 /* don't allow zero width/height picturees
1109 * this ends the picture drawing behavior
1110 * we want this? hack */
1111 if ((GET_PICTURE_WIDTH(w_current) == 0) || (GET_PICTURE_HEIGHT(w_current) == 0)) {
1112 o_picture_invalidate_rubber (w_current);
1113 o_invalidate (w_current, o_current);
1114 return;
1117 o_picture_modify(toplevel, o_current,
1118 w_current->second_wx, w_current->second_wy, whichone);
1120 g_object_unref (w_current->current_pixbuf);
1121 w_current->current_pixbuf = NULL;
1122 g_free (w_current->pixbuf_filename);
1123 w_current->pixbuf_filename = NULL;
1124 w_current->pixbuf_wh_ratio = 0;
1127 /*! \brief End process of modifying circle object with grip.
1128 * \par Function Description
1129 * This function ends the process of modifying the radius of the circle
1130 * object <B>*o_current</B>.
1131 * The modified circle is finally normally drawn.
1133 * A circle with a null radius is not allowed. In this case, the process
1134 * is stopped and the circle is left unchanged.
1136 * The last value of the radius is in <B>w_current->distance</B> in screen units.
1138 * \param [in] w_current The GschemToplevel object.
1139 * \param [in] o_current Circle OBJECT to end modification on.
1140 * \param [in] whichone Which grip is pointed to.
1142 static void o_grips_end_circle(GschemToplevel *w_current, OBJECT *o_current,
1143 int whichone)
1145 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1147 /* don't allow zero radius circles
1148 * this ends the circle drawing behavior
1149 * we want this? hack */
1150 if (w_current->distance == 0) {
1151 o_circle_invalidate_rubber (w_current);
1152 o_invalidate (w_current, o_current);
1153 return;
1156 /* modify the radius of the circle */
1157 o_circle_modify(toplevel, o_current, w_current->distance, -1, CIRCLE_RADIUS);
1160 /*! \brief End process of modifying line object with grip.
1161 * \par Function Description
1162 * This function ends the process of modifying one end of the line
1163 * object <B>*o_current</B>.
1164 * This end is identified by <B>whichone</B>. The line object is modified
1165 * according to the <B>whichone</B> parameter and the last position of the
1166 * line end.
1167 * The modified line is finally normally drawn.
1169 * A line with a null width, i.e. when both ends are identical, is not
1170 * allowed. In this case, the process is stopped and the line unchanged.
1172 * \param [in] w_current The GschemToplevel object.
1173 * \param [in] o_current Line OBJECT to end modification on.
1174 * \param [in] whichone Which grip is pointed to.
1176 static void o_grips_end_line(GschemToplevel *w_current, OBJECT *o_current,
1177 int whichone)
1179 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1181 /* don't allow zero length line
1182 * this ends the net drawing behavior
1183 * we want this? hack */
1184 if ((w_current->first_wx == w_current->second_wx) &&
1185 (w_current->first_wy == w_current->second_wy)) {
1186 o_box_invalidate_rubber (w_current);
1187 o_invalidate (w_current, o_current);
1188 return;
1191 /* modify the right line end according to whichone */
1192 o_line_modify(toplevel, o_current,
1193 w_current->second_wx, w_current->second_wy, whichone);
1197 /*! \brief End process of modifying net object with grip.
1198 * \par Function Description
1199 * This function ends the process of modifying one end of the net
1200 * object <B>*o_current</B>.
1201 * This end is identified by <B>whichone</B>. The line object is modified
1202 * according to the <B>whichone</B> parameter and the last position of the
1203 * line end.
1204 * The connections to the modified net are checked and recreated if neccessary.
1206 * A net with zero length, i.e. when both ends are identical, is not
1207 * allowed. In this case, the process is stopped and the line unchanged.
1209 * \param [in] w_current The GschemToplevel object.
1210 * \param [in] o_current Net OBJECT to end modification on.
1211 * \param [in] whichone Which grip is pointed to.
1213 static void o_grips_end_net(GschemToplevel *w_current, OBJECT *o_current,
1214 int whichone)
1216 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1217 GList *connected_objects;
1219 /* don't allow zero length net
1220 * this ends the net drawing behavior
1221 * we want this? hack */
1222 if ((w_current->first_wx == w_current->second_wx) &&
1223 (w_current->first_wy == w_current->second_wy)) {
1224 o_invalidate (w_current, o_current);
1225 return;
1228 s_conn_remove_object_connections (toplevel, o_current);
1229 o_net_modify (toplevel, o_current, w_current->second_wx,
1230 w_current->second_wy, w_current->which_grip);
1231 s_conn_update_object (o_current->page, o_current);
1233 /* add bus rippers if necessary */
1234 connected_objects = s_conn_return_others (NULL, o_current);
1235 o_net_add_busrippers (w_current, o_current, connected_objects);
1236 g_list_free (connected_objects);
1239 /*! \brief End process of modifying pin object with grip.
1240 * \par Function Description
1241 * This function ends the process of modifying one end of the pin
1242 * object <B>*o_current</B>.
1243 * This end is identified by <B>whichone</B>. The pin object is modified
1244 * according to the <B>whichone</B> parameter and the last position of the
1245 * pin end.
1246 * The connections to the modified pin are checked and recreated if neccessary.
1248 * \note In contrast to lines, nets, and buses, pins with zero length
1249 * (i.e. when both ends are identical) are allowed.
1251 * \param [in] w_current The GschemToplevel object.
1252 * \param [in] o_current Net OBJECT to end modification on.
1253 * \param [in] whichone Which grip is pointed to.
1255 static void o_grips_end_pin(GschemToplevel *w_current, OBJECT *o_current,
1256 int whichone)
1258 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1260 s_conn_remove_object_connections (toplevel, o_current);
1261 o_pin_modify (toplevel, o_current, w_current->second_wx,
1262 w_current->second_wy, w_current->which_grip);
1263 s_conn_update_object (o_current->page, o_current);
1266 /*! \brief End process of modifying bus object with grip.
1267 * \par Function Description
1268 * This function ends the process of modifying one end of the bus
1269 * object <B>*o_current</B>.
1270 * This end is identified by <B>whichone</B>. The line object is modified
1271 * according to the <B>whichone</B> parameter and the last position of the
1272 * bus end.
1273 * The connections to the modified bus are checked and recreated if neccessary.
1275 * A bus with zero length, i.e. when both ends are identical, is not
1276 * allowed. In this case, the process is stopped and the bus unchanged.
1278 * \param [in] w_current The GschemToplevel object.
1279 * \param [in] o_current bus OBJECT to end modification on.
1280 * \param [in] whichone Which grip is pointed to.
1282 static void o_grips_end_bus(GschemToplevel *w_current, OBJECT *o_current,
1283 int whichone)
1285 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1287 /* don't allow zero length bus
1288 * this ends the bus changing behavior
1289 * we want this? hack */
1290 if ((w_current->first_wx == w_current->second_wx) &&
1291 (w_current->first_wy == w_current->second_wy)) {
1292 o_invalidate (w_current, o_current);
1293 return;
1296 s_conn_remove_object_connections (toplevel, o_current);
1297 o_bus_modify (toplevel, o_current, w_current->second_wx,
1298 w_current->second_wy, w_current->which_grip);
1299 s_conn_update_object (o_current->page, o_current);
1303 /*! \brief End process of modifying object with grip.
1304 * \par Function Description
1305 * This function ends the process of modifying a parameter of an object
1306 * with a grip.
1307 * The temporary representation of the object is erased, the object is
1308 * modified and finally drawn.
1310 * The object under modification is <B>w_current->which_object</B> and
1311 * the grip concerned is <B>w_current->which_grip</B>.
1313 * Depending on the object type, a specific function is used. It erases
1314 * the temporary object, updates the object and draws the modified object
1315 * normally.
1317 * \param [in,out] w_current The GschemToplevel object.
1319 void o_grips_end(GschemToplevel *w_current)
1321 TOPLEVEL *toplevel = gschem_toplevel_get_toplevel (w_current);
1322 OBJECT *object;
1323 int grip;
1325 g_assert (w_current->inside_action != 0);
1327 object = w_current->which_object;
1328 grip = w_current->which_grip;
1330 if (!object) {
1331 /* actually this is an error condition hack */
1332 i_action_stop (w_current);
1333 i_set_state(w_current, SELECT);
1334 return;
1337 switch(object->type) {
1339 case(OBJ_ARC):
1340 /* modify an arc object */
1341 o_grips_end_arc(w_current, object, grip);
1342 break;
1344 case(OBJ_BOX):
1345 /* modify a box object */
1346 o_grips_end_box(w_current, object, grip);
1347 break;
1349 case(OBJ_PATH):
1350 /* modify a path object */
1351 o_grips_end_path(w_current, object, grip);
1352 break;
1354 case(OBJ_PICTURE):
1355 /* modify a picture object */
1356 o_grips_end_picture(w_current, object, grip);
1357 break;
1359 case(OBJ_CIRCLE):
1360 /* modify a circle object */
1361 o_grips_end_circle(w_current, object, grip);
1362 break;
1364 case(OBJ_LINE):
1365 /* modify a line object */
1366 o_grips_end_line(w_current, object, grip);
1367 break;
1369 case(OBJ_NET):
1370 /* modify a net object */
1371 o_grips_end_net(w_current, object, grip);
1372 break;
1374 case(OBJ_PIN):
1375 /* modify a pin object */
1376 o_grips_end_pin(w_current, object, grip);
1377 break;
1379 case(OBJ_BUS):
1380 /* modify a bus object */
1381 o_grips_end_bus(w_current, object, grip);
1382 break;
1384 default:
1385 return;
1388 /* Switch drawing of the object back on */
1389 object->dont_redraw = FALSE;
1390 o_invalidate (w_current, object);
1392 /* reset global variables */
1393 w_current->which_grip = -1;
1394 w_current->which_object = NULL;
1396 w_current->rubber_visible = 0;
1398 gschem_toplevel_page_content_changed (w_current, toplevel->page_current);
1399 o_undo_savestate_old (w_current, UNDO_ALL, _("Move Handle"));
1401 i_set_state(w_current, SELECT);
1402 i_action_stop (w_current);
1406 /*! \brief Draw objects being grip maniuplated from GschemToplevel object.
1408 * \par Function Description
1409 * This function draws the objects being grip manipulated.
1411 * \param [in] w_current The GschemToplevel object.
1413 void o_grips_draw_rubber (GschemToplevel *w_current, EdaRenderer *renderer)
1415 g_return_if_fail (w_current->which_object != NULL);
1417 switch(w_current->which_object->type) {
1418 case OBJ_ARC:
1419 o_arc_draw_rubber (w_current, renderer);
1420 break;
1422 case OBJ_BOX:
1423 o_box_draw_rubber (w_current, renderer);
1424 break;
1426 case OBJ_PATH:
1427 o_path_draw_rubber_grips (w_current, renderer);
1428 break;
1430 case OBJ_PICTURE:
1431 o_picture_draw_rubber (w_current, renderer);
1432 break;
1434 case OBJ_CIRCLE:
1435 o_circle_draw_rubber (w_current, renderer);
1436 break;
1438 case OBJ_LINE:
1439 case OBJ_NET:
1440 case OBJ_PIN:
1441 case OBJ_BUS:
1442 o_line_draw_rubber (w_current, renderer);
1443 break;
1445 default:
1446 g_return_if_reached ();