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
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
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
)
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
);
82 /* get the size of the grip according to zoom level */
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
;
90 switch(object
->type
) {
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
;
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
;
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
;
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
;
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
;
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
;
141 s_current
= g_list_next(s_current
);
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 :
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>.
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
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
;
345 for (i
= 0; i
< o_current
->path
->num_sections
; i
++) {
346 section
= &o_current
->path
->sections
[i
];
348 switch (section
->code
) {
350 /* inside first control grip ? */
351 if (inside_grip(x
, y
, section
->x1
, section
->y1
, size
)) {
356 /* inside second control grip ? */
357 if (inside_grip(x
, y
, section
->x2
, section
->y2
, size
)) {
364 case PATH_MOVETO_OPEN
:
366 /* inside destination control grip ? */
367 if (inside_grip(x
, y
, section
->x3
, section
->y3
, size
)) {
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
;
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
;
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
;
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
;
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>
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
,
479 *whichone
= CIRCLE_RADIUS
;
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
;
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
;
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
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 */
560 w_current
->first_wx
= o_current
->arc
->x
;
561 w_current
->first_wy
= o_current
->arc
->y
;
563 w_current
->distance
= o_current
->arc
->radius
;
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 */
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
;
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
;
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
;
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
;
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
;
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
) {
673 /* Two control point grips */
674 if (whichone
== grip_no
++) {
678 if (whichone
== grip_no
++) {
684 case PATH_MOVETO_OPEN
:
686 /* Destination point grip */
687 if (whichone
== grip_no
++) {
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 */
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
;
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
;
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
;
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
;
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
)
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
);
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;
894 case OBJ_BUS
: func
= o_grips_start_line
; break;
899 /* start the modification of a grip on the object */
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
) {
935 o_arc_motion (w_current
, w_x
, w_y
, grip
);
939 o_box_motion (w_current
, w_x
, w_y
);
943 o_path_motion_grips (w_current
, w_x
, w_y
);
947 o_picture_motion (w_current
, w_x
, w_y
);
951 o_circle_motion (w_current
, w_x
, w_y
);
958 o_line_motion (w_current
, w_x
, w_y
);
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
,
1014 TOPLEVEL
*toplevel
= gschem_toplevel_get_toplevel (w_current
);
1017 /* erase the temporary arc */
1018 /* o_arc_invalidate_rubber (w_current); */
1020 /* determination of the parameters to give to o_arc_modify() */
1023 /* get the radius from w_current */
1024 arg1
= w_current
->distance
;
1025 /* second parameter is not used */
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 */
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 */
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
,
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
);
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
,
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
,
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
);
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
,
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
);
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
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
,
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
);
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
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
,
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
);
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
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
,
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
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
,
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
);
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
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
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
);
1325 g_assert (w_current
->inside_action
!= 0);
1327 object
= w_current
->which_object
;
1328 grip
= w_current
->which_grip
;
1331 /* actually this is an error condition hack */
1332 i_action_stop (w_current
);
1333 i_set_state(w_current
, SELECT
);
1337 switch(object
->type
) {
1340 /* modify an arc object */
1341 o_grips_end_arc(w_current
, object
, grip
);
1345 /* modify a box object */
1346 o_grips_end_box(w_current
, object
, grip
);
1350 /* modify a path object */
1351 o_grips_end_path(w_current
, object
, grip
);
1355 /* modify a picture object */
1356 o_grips_end_picture(w_current
, object
, grip
);
1360 /* modify a circle object */
1361 o_grips_end_circle(w_current
, object
, grip
);
1365 /* modify a line object */
1366 o_grips_end_line(w_current
, object
, grip
);
1370 /* modify a net object */
1371 o_grips_end_net(w_current
, object
, grip
);
1375 /* modify a pin object */
1376 o_grips_end_pin(w_current
, object
, grip
);
1380 /* modify a bus object */
1381 o_grips_end_bus(w_current
, object
, grip
);
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
) {
1419 o_arc_draw_rubber (w_current
, renderer
);
1423 o_box_draw_rubber (w_current
, renderer
);
1427 o_path_draw_rubber_grips (w_current
, renderer
);
1431 o_picture_draw_rubber (w_current
, renderer
);
1435 o_circle_draw_rubber (w_current
, renderer
);
1442 o_line_draw_rubber (w_current
, renderer
);
1446 g_return_if_reached ();