refdes_renum: warn of possible number clash with non-conforming values
[geda-gaf/whiteaudio.git] / gschem / src / o_grips.c
blob1bc8e54d5f82a5254bd992f2dfa3f65e0c9a0f13
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2010 Ales Hvezda
4 * Copyright (C) 1998-2010 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 #ifdef HAVE_LIBDMALLOC
28 #include <dmalloc.h>
29 #endif
31 #define GET_BOX_WIDTH(w) abs((w)->second_wx - (w)->first_wx)
32 #define GET_BOX_HEIGHT(w) abs((w)->second_wy - (w)->first_wy)
34 #define GET_PICTURE_WIDTH(w) \
35 abs((w)->second_wx - (w)->first_wx)
36 #define GET_PICTURE_HEIGHT(w) \
37 (w)->pixbuf_wh_ratio == 0 ? 0 : abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio
38 #define GET_PICTURE_LEFT(w) \
39 min((w)->first_wx, (w)->second_wx)
40 #define GET_PICTURE_TOP(w) \
41 (w)->first_wy > (w)->second_wy ? (w)->first_wy : \
42 (w)->first_wy+abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio
45 /*! \brief Check if point is inside grip.
46 * \par Function Description
47 * This function is used to determine if the (<B>x</B>,<B>y</B>) point is
48 * inside a grip of one of the selected object on the current sheet.
49 * The selected object are in a list starting at
50 * <B>w_current->toplevel->page_current->selection2_head</B>.
51 * The <B>x</B> and <B>y</B> parameters are in world units.
52 * If the point is inside one grip, a pointer on the object it belongs to is
53 * returned and <B>*whichone</B> is set according to the position of the grip
54 * on the object.
55 * Else, <B>*whichone</B> is unchanged and the function returns <B>NULL</B>.
57 * A specific search function is provided for every kind of graphical object.
58 * The list of selected object is covered : each object is tested with the
59 * appropriate function.
61 * \param [in] w_current The GSCHEM_TOPLEVEL object.
62 * \param [in] x Current x coordinate of pointer in world units.
63 * \param [in] y Current y coordinate of pointer in world units.
64 * \param [out] whichone Which grip point is selected.
65 * \return Pointer to OBJECT the grip is on, NULL otherwise.
67 OBJECT *o_grips_search_world(GSCHEM_TOPLEVEL *w_current, int x, int y, int *whichone)
69 TOPLEVEL *toplevel = w_current->toplevel;
70 OBJECT *object=NULL;
71 OBJECT *found=NULL;
72 GList *s_current;
73 int size;
74 int w_size;
76 if (!whichone) {
77 return(NULL);
80 /* get the size of the grip according to zoom level */
81 size = o_grips_size(w_current);
82 w_size = WORLDabs (w_current, size );
84 s_current = geda_list_get_glist( toplevel->page_current->selection_list );
85 while (s_current != NULL) {
86 object = (OBJECT *) s_current->data;
87 if (object) {
88 switch(object->type) {
89 case(OBJ_ARC):
90 /* check the grips of the arc object */
91 found = o_grips_search_arc_world(w_current, object,
92 x, y, w_size, whichone);
93 if(found != NULL) return found;
94 break;
96 case(OBJ_BOX):
97 /* check the grips of the box object */
98 found = o_grips_search_box_world(w_current, object,
99 x, y, w_size, whichone);
100 if(found != NULL) return found;
101 break;
103 case(OBJ_PATH):
104 /* check the grips of the path object */
105 found = o_grips_search_path_world(w_current, object,
106 x, y, w_size, whichone);
107 if(found != NULL) return found;
108 break;
110 case(OBJ_PICTURE):
111 /* check the grips of the picture object */
112 found = o_grips_search_picture_world(w_current, object,
113 x, y, w_size, whichone);
114 if(found != NULL) return found;
115 break;
117 case(OBJ_CIRCLE):
118 /* check the grips of the circle object */
119 found = o_grips_search_circle_world(w_current, object,
120 x, y, w_size, whichone);
121 if(found != NULL) return found;
122 break;
124 case(OBJ_LINE):
125 case(OBJ_PIN):
126 case(OBJ_NET):
127 case(OBJ_BUS):
128 /* check the grips of the line object */
129 /* the function is the same for line, pin, net, bus */
130 found = o_grips_search_line_world(w_current, object,
131 x, y, w_size, whichone);
132 if(found != NULL) return found;
133 break;
135 default:
136 break;
139 s_current = g_list_next(s_current);
142 return(NULL);
146 /*! \brief Check if pointer is inside the grip region.
148 * \par Function Description
149 * This function checks if the point (<B>x</B>,<B>y</B>) is
150 * inside the grip centered at (<B>grip_x</B>,<B>grip_y</B>).
152 * \param [in] x Current x coordinate of pointer in world units.
153 * \param [in] y Current y coordinate of pointer in world units.
154 * \param [in] grip_x Current x coordinate of grip center in world units.
155 * \param [in] grip_y Current y coordinate of grip center in world units.
156 * \param [in] size Half the width of the grip square in world units.
157 * \return True / False whether the mouse pointer is inside the grip.
159 static gboolean inside_grip( int x, int y, int grip_x, int grip_y, int size )
161 int xmin, ymin, xmax, ymax;
163 xmin = grip_x - size;
164 ymin = grip_y - size;
165 xmax = xmin + 2 * size;
166 ymax = ymin + 2 * size;
168 return inside_region(xmin, ymin, xmax, ymax, x, y);
171 /*! \brief Check if pointer is inside arc grip.
172 * \par Function Description
173 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
174 * inside one of the grips of an <B>o_current</B> pointed arc object. If so
175 * the <B>whichone</B> pointed integer is set to the number of this grip and
176 * the return pointer is a pointer on this object. If the point is not
177 * inside a grip the function returns a NULL pointer and the <B>whichone</B>
178 * pointed integer is unset.
180 * An arc object has three grips :
181 * <DL>
182 * <DT>*</DT><DD>one at the center of the arc. This grip is used to modify
183 * the radius of the arc. If this one is selected, the
184 * <B>whichone</B> pointed integer is set to <B>ARC_RADIUS</B>.
185 * <DT>*</DT><DD>one at one end of the arc. It corresponds to the starting
186 * angle of the arc. If this one is selected, the
187 * <B>whichone</B> pointed integer is set to <B>ARC_START_ANGLE</B>.
188 * <DT>*</DT><DD>one at the other end of the arc. It corresponds to the
189 * ending angle of the arc. If this one is selected, the
190 * <B>whichone</B> pointed integer is set to <B>ARC_END_ANGLE</B>.
191 * </DL>
193 * The <B>x</B> and <B>y</B> parameters are in world units.
195 * The <B>size</B> parameter is the width (and height) of the square
196 * representing a grip in world units.
198 * \param [in] w_current The GSCHEM_TOPLEVEL object.
199 * \param [in] o_current Arc OBJECT to check.
200 * \param [in] x Current x coordinate of pointer in world units.
201 * \param [in] y Current y coordinate of pointer in world units.
202 * \param [in] size Half the width of the grip square in world units.
203 * \param [out] whichone Which grip point is selected.
204 * \return Pointer to OBJECT the grip is on, NULL otherwise.
206 OBJECT *o_grips_search_arc_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
207 int x, int y, int size, int *whichone)
209 int centerx, centery, radius, start_angle, end_angle;
210 double tmp;
212 centerx = o_current->arc->x;
213 centery = o_current->arc->y;
214 radius = o_current->arc->width / 2;
215 start_angle = o_current->arc->start_angle;
216 end_angle = o_current->arc->end_angle;
218 /* check the grip on the center of the arc */
219 if (inside_grip(x, y, centerx, centery, size)) {
220 *whichone = ARC_RADIUS;
221 return(o_current);
224 /* check the grip at the end angle of the arc */
225 tmp = ((double) start_angle + end_angle) * M_PI / 180;
226 if (inside_grip(x, y,
227 centerx + radius * cos(tmp),
228 centery + radius * sin(tmp), size)) {
229 *whichone = ARC_END_ANGLE;
230 return(o_current);
233 /* check the grip at the start angle of the arc */
234 tmp = ((double) start_angle) * M_PI / 180;
235 if (inside_grip(x, y,
236 centerx + radius * cos(tmp),
237 centery + radius * sin(tmp), size)) {
238 *whichone = ARC_START_ANGLE;
239 return(o_current);
242 return NULL;
245 /*! \brief Check if pointer is inside box grip.
246 * \par Function Description
247 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>) is
248 * inside one of the grips of the <B>o_current</B> pointed box object.
249 * If so, the <B>whichone</B> pointed integer is set to the identifier of
250 * this grip and the returned pointer is a pointer on this object.
251 * If the point is not inside a grip the function returns a NULL pointer
252 * and the <B>whichone</B> pointed integer is unset.
254 * A box object has four grips : one at each corner of the box. The
255 * identifiers of each corner are <B>BOX_UPPER_LEFT</B>,
256 * <B>BOX_UPPER_RIGHT</B>, <B>BOX_LOWER_LEFT</B> and <B>BOX_LOWER_RIGHT</B>.
258 * The <B>x</B> and <B>y</B> parameters are in world units.
260 * The <B>size</B> parameter is half the width (and half the height) of
261 * the square representing a grip in world units.
263 * \param [in] w_current The GSCHEM_TOPLEVEL object.
264 * \param [in] o_current Box OBJECT to check.
265 * \param [in] x Current x coordinate of pointer in world units.
266 * \param [in] y Current y coordinate of pointer in world units.
267 * \param [in] size Half the width of the grip square in world units.
268 * \param [out] whichone Which grip point is selected.
269 * \return Pointer to OBJECT the grip is on, NULL otherwise.
271 OBJECT *o_grips_search_box_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
272 int x, int y, int size, int *whichone)
274 /* inside upper left grip ? */
275 if (inside_grip(x, y,
276 o_current->box->upper_x,
277 o_current->box->upper_y, size)) {
278 *whichone = BOX_UPPER_LEFT;
279 return(o_current);
282 /* inside lower right grip ? */
283 if (inside_grip(x, y,
284 o_current->box->lower_x,
285 o_current->box->lower_y, size)) {
286 *whichone = BOX_LOWER_RIGHT;
287 return(o_current);
290 /* inside upper right grip ? */
291 if (inside_grip(x, y,
292 o_current->box->lower_x,
293 o_current->box->upper_y, size)) {
294 *whichone = BOX_UPPER_RIGHT;
295 return(o_current);
298 /* inside lower left grip ? */
299 if (inside_grip(x, y,
300 o_current->box->upper_x,
301 o_current->box->lower_y, size)) {
302 *whichone = BOX_LOWER_LEFT;
303 return(o_current);
306 return NULL;
309 /*! \brief Check if pointer is inside path grip.
310 * \par Function Description
311 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>)
312 * is inside one of the grips of the <B>o_current</B> pointed path object.
313 * If so, the <B>whichone</B> pointed integer is set to the identifier of
314 * this grip and the returned pointer is a pointer on this object.
315 * If the point is not inside a grip the function returns a NULL pointer
316 * and the <B>whichone</B> pointed integer is unset.
318 * A path object has four grips : one at each corner of the path.
319 * The identifiers of each corner are #PICTURE_UPPER_LEFT,
320 * #PICTURE_UPPER_RIGHT, #PICTURE_LOWER_LEFT and
321 * #PICTURE_LOWER_RIGHT.
323 * The <B>x</B> and <B>y</B> parameters are in world units.
325 * The <B>size</B> parameter is half the width (and half the height) of the
326 * square representing a grip in world units.
328 * \param [in] w_current The GSCHEM_TOPLEVEL object.
329 * \param [in] o_current Picture OBJECT to check.
330 * \param [in] x Current x coordinate of pointer in world units.
331 * \param [in] y Current y coordinate of pointer in world units.
332 * \param [in] size Half the width of the grip square in world units.
333 * \param [out] whichone Which grip point is selected.
334 * \return Pointer to OBJECT the grip is on, NULL otherwise.
336 OBJECT *o_grips_search_path_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
337 int x, int y, int size, int *whichone)
339 PATH_SECTION *section;
340 int i;
341 int grip_no = 0;
343 for (i = 0; i < o_current->path->num_sections; i++) {
344 section = &o_current->path->sections[i];
346 switch (section->code) {
347 case PATH_CURVETO:
348 /* inside first control grip ? */
349 if (inside_grip(x, y, section->x1, section->y1, size)) {
350 *whichone = grip_no;
351 return o_current;
353 grip_no ++;
354 /* inside second control grip ? */
355 if (inside_grip(x, y, section->x2, section->y2, size)) {
356 *whichone = grip_no;
357 return o_current;
359 grip_no ++;
360 /* Fall through */
361 case PATH_MOVETO:
362 case PATH_MOVETO_OPEN:
363 case PATH_LINETO:
364 /* inside destination control grip ? */
365 if (inside_grip(x, y, section->x3, section->y3, size)) {
366 *whichone = grip_no;
367 return o_current;
369 grip_no ++;
370 break;
371 case PATH_END:
372 break;
376 return NULL;
379 /*! \brief Check if pointer is inside picture grip.
380 * \par Function Description
381 * This function checks if the pointer event occuring at (<B>x</B>,<B>y</B>)
382 * is inside one of the grips of the <B>o_current</B> pointed picture object.
383 * If so, the <B>whichone</B> pointed integer is set to the identifier of
384 * this grip and the returned pointer is a pointer on this object.
385 * If the point is not inside a grip the function returns a NULL pointer
386 * and the <B>whichone</B> pointed integer is unset.
388 * A picture object has four grips : one at each corner of the picture.
389 * The identifiers of each corner are #PICTURE_UPPER_LEFT,
390 * #PICTURE_UPPER_RIGHT, #PICTURE_LOWER_LEFT and
391 * #PICTURE_LOWER_RIGHT.
393 * The <B>x</B> and <B>y</B> parameters are in world units.
395 * The <B>size</B> parameter is half the width (and half the height) of the
396 * square representing a grip in world units.
398 * \param [in] w_current The GSCHEM_TOPLEVEL object.
399 * \param [in] o_current Picture OBJECT to check.
400 * \param [in] x Current x coordinate of pointer in world units.
401 * \param [in] y Current y coordinate of pointer in world units.
402 * \param [in] size Half the width of the grip square in world units.
403 * \param [out] whichone Which grip point is selected.
404 * \return Pointer to OBJECT the grip is on, NULL otherwise.
406 OBJECT *o_grips_search_picture_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
407 int x, int y, int size, int *whichone)
409 /* inside upper left grip ? */
410 if (inside_grip(x, y,
411 o_current->picture->upper_x,
412 o_current->picture->upper_y, size)) {
413 *whichone = PICTURE_UPPER_LEFT;
414 return(o_current);
417 /* inside lower right grip ? */
418 if (inside_grip(x, y,
419 o_current->picture->lower_x,
420 o_current->picture->lower_y, size)) {
421 *whichone = PICTURE_LOWER_RIGHT;
422 return(o_current);
425 /* inside upper right grip ? */
426 if (inside_grip(x, y,
427 o_current->picture->lower_x,
428 o_current->picture->upper_y, size)) {
429 *whichone = PICTURE_UPPER_RIGHT;
430 return(o_current);
433 /* inside lower left grip ? */
434 if (inside_grip(x, y,
435 o_current->picture->upper_x,
436 o_current->picture->lower_y, size)) {
437 *whichone = PICTURE_LOWER_LEFT;
438 return(o_current);
441 return NULL;
444 /*! \brief Check if pointer is inside circle grip.
445 * \par Function Description
446 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
447 * the grip of the circle object <B>o_current</B>.
448 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
449 * is in one of these areas.
450 * If the event occured in one of the grip, a pointer on the object is
451 * returned and <B>*whichone</B> is set to the identifier of the grip.
452 * If not, the function returns a <B>NULL</B> pointer and <B>*whichone</B>
453 * is unchanged.
455 * The parameter <B>size</B> is half the size of the grip in world units.
457 * A circle has only one grip on the lower right corner of the box it
458 * is inscribed in. Moving this grip change the radius of the circle.
459 * The identifier of this grip is <B>CIRCLE_RADIUS</B>.
461 * \param [in] w_current The GSCHEM_TOPLEVEL object.
462 * \param [in] o_current Circle OBJECT to check.
463 * \param [in] x Current x coordinate of pointer in world units.
464 * \param [in] y Current y coordinate of pointer in world units.
465 * \param [in] size Half the width of the grip square in world units.
466 * \param [out] whichone Which grip point is selected.
467 * \return Pointer to OBJECT the grip is on, NULL otherwise.
469 OBJECT *o_grips_search_circle_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
470 int x, int y, int size, int *whichone)
472 /* check the grip for radius */
473 if (inside_grip(x, y,
474 o_current->circle->center_x + o_current->circle->radius,
475 o_current->circle->center_y - o_current->circle->radius,
476 size)) {
477 *whichone = CIRCLE_RADIUS;
478 return(o_current);
481 return NULL;
484 /*! \brief Check if pointer is inside line grip.
485 * \par Function Description
486 * This function determines if the (<B>x</B>,<B>y</B>) point is inside one of
487 * the grip of the line object <B>o_current</B>.
488 * It computes the area covered by each grip and check if (<B>x</B>,<B>y</B>)
489 * is in one of these areas.
490 * If the event occured in one of its grip, a pointer on the object is
491 * returned and <B>*whichone</B> is set to the identifier of the grip. If not,
492 * the function returns <B>NULL</B> pointer and <B>*whichone</B> is unchanged.
494 * The parameter <B>size</B> is half the size of the grip in world units.
496 * \param [in] w_current The GSCHEM_TOPLEVEL object.
497 * \param [in] o_current Line OBJECT to check.
498 * \param [in] x Current x coordinate of pointer in world units.
499 * \param [in] y Current y coordinate of pointer in world units.
500 * \param [in] size Half the width of the grip square in world units.
501 * \param [out] whichone Which grip point is selected.
502 * \return Pointer to OBJECT the grip is on, NULL otherwise.
504 OBJECT *o_grips_search_line_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
505 int x, int y, int size, int *whichone)
507 /* check the grip on the end of line 1 */
508 if (inside_grip(x, y,
509 o_current->line->x[LINE_END1],
510 o_current->line->y[LINE_END1], size)) {
511 *whichone = LINE_END1;
512 return(o_current);
515 /* check the grip on the end of line 2 */
516 if (inside_grip(x, y,
517 o_current->line->x[LINE_END2],
518 o_current->line->y[LINE_END2], size)) {
519 *whichone = LINE_END2;
520 return(o_current);
523 return NULL;
526 /*! \brief Initialize grip motion process for an arc.
527 * \par Function Description
528 * This function initializes the grip motion process for an arc.
529 * From the <B>o_current</B> pointed object, it stores into the
530 * GSCHEM_TOPLEVEL structure the coordinates of the center, the radius
531 * and the two angle that describes an arc. These variables are used in
532 * the grip process.
534 * The coordinates of the center of the arc on x- and y-axis are stored
535 * into the <B>first_wx</B> and <B>first_wy</B> fields of the GSCHEM_TOPLEVEL
536 * structure in screen units.
538 * The radius of the center is stored into the <B>distance</B> field of
539 * the GSCHEM_TOPLEVEL structure in screen units.
541 * The two angles describing the arc on a circle are stored into the
542 * <B>second_wx</B> for the starting angle and <B>second_wy</B> for the ending angle.
543 * These angles are expressed in degrees.
545 * \param [in] w_current The GSCHEM_TOPLEVEL object.
546 * \param [in] o_current Arc OBJECT to check.
547 * \param [in] x (unused)
548 * \param [in] y (unused)
549 * \param [out] whichone (unused)
551 static void o_grips_start_arc(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
552 int x, int y, int whichone)
554 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
556 /* describe the arc with GSCHEM_TOPLEVEL variables */
557 /* center */
558 w_current->first_wx = o_current->arc->x;
559 w_current->first_wy = o_current->arc->y;
560 /* radius */
561 w_current->distance = o_current->arc->width / 2;
562 /* angles */
563 w_current->second_wx = o_current->arc->start_angle;
564 w_current->second_wy = o_current->arc->end_angle;
566 /* draw the first temporary arc */
567 /* o_arc_invalidate_rubber (w_current); */
568 w_current->rubber_visible = 1;
571 /*! \brief Initialize grip motion process for a box.
572 * \par Function Description
573 * This function initializes the grip motion process for a box. From the
574 * <B>o_current</B> pointed object, it stores into the GSCHEM_TOPLEVEL
575 * structure the .... These variables are used in the grip process.
577 * The function first erases the grips.
579 * The coordinates of the selected corner are put in
580 * (<B>w_current->second_wx</B>,<B>w_current->second_wx</B>).
582 * The coordinates of the opposite corner go in
583 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
584 * to change during the action.
586 * \param [in] w_current The GSCHEM_TOPLEVEL object.
587 * \param [in] o_current Box OBJECT to check.
588 * \param [in] x (unused)
589 * \param [in] y (unused)
590 * \param [out] whichone Which coordinate to check.
592 static void o_grips_start_box(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
593 int x, int y, int whichone)
595 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
597 /* (second_wx, second_wy) is the selected corner */
598 /* (first_wx, first_wy) is the opposite corner */
599 switch(whichone) {
600 case BOX_UPPER_LEFT:
601 w_current->second_wx = o_current->box->upper_x;
602 w_current->second_wy = o_current->box->upper_y;
603 w_current->first_wx = o_current->box->lower_x;
604 w_current->first_wy = o_current->box->lower_y;
605 break;
606 case BOX_LOWER_RIGHT:
607 w_current->second_wx = o_current->box->lower_x;
608 w_current->second_wy = o_current->box->lower_y;
609 w_current->first_wx = o_current->box->upper_x;
610 w_current->first_wy = o_current->box->upper_y;
611 break;
612 case BOX_UPPER_RIGHT:
613 w_current->second_wx = o_current->box->lower_x;
614 w_current->second_wy = o_current->box->upper_y;
615 w_current->first_wx = o_current->box->upper_x;
616 w_current->first_wy = o_current->box->lower_y;
617 break;
618 case BOX_LOWER_LEFT:
619 w_current->second_wx = o_current->box->upper_x;
620 w_current->second_wy = o_current->box->lower_y;
621 w_current->first_wx = o_current->box->lower_x;
622 w_current->first_wy = o_current->box->upper_y;
623 break;
624 default:
625 return; /* error */
628 /* draw the first temporary box */
629 /* o_box_invalidate_rubber (w_current); */
630 w_current->rubber_visible = 1;
633 /*! \brief Initialize grip motion process for a path.
634 * \par Function Description
635 * This function initializes the grip motion process for a path.
636 * From the <B>o_current</B> pointed object, it stores into the
637 * GSCHEM_TOPLEVEL structure the ....
638 * These variables are used in the grip process.
640 * The function first erases the grips.
642 * The coordinates of the selected corner are put in
643 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
645 * The coordinates of the opposite corner go in
646 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
647 * suppose to change during the action.
649 * \param [in] w_current The GSCHEM_TOPLEVEL object.
650 * \param [in] o_current Picture OBJECT to check.
651 * \param [in] x (unused)
652 * \param [in] y (unused)
653 * \param [out] whichone Which coordinate to check.
655 static void o_grips_start_path(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
656 int x, int y, int whichone)
658 PATH_SECTION *section;
659 int i;
660 int grip_no = 0;
661 int gx = -1;
662 int gy = -1;
664 w_current->last_drawb_mode = -1;
666 for (i = 0; i < o_current->path->num_sections; i++) {
667 section = &o_current->path->sections[i];
669 switch (section->code) {
670 case PATH_CURVETO:
671 /* Two control point grips */
672 if (whichone == grip_no++) {
673 gx = section->x1;
674 gy = section->y1;
676 if (whichone == grip_no++) {
677 gx = section->x2;
678 gy = section->y2;
680 /* Fall through */
681 case PATH_MOVETO:
682 case PATH_MOVETO_OPEN:
683 case PATH_LINETO:
684 /* Destination point grip */
685 if (whichone == grip_no++) {
686 gx = section->x3;
687 gy = section->y3;
689 break;
690 case PATH_END:
691 break;
695 w_current->first_wx = w_current->second_wx = gx;
696 w_current->first_wy = w_current->second_wy = gy;
698 /* draw the first temporary path */
699 /* o_path_invalidate_rubber (w_current); */
700 w_current->rubber_visible = 1;
703 /*! \brief Initialize grip motion process for a picture.
704 * \par Function Description
705 * This function initializes the grip motion process for a picture.
706 * From the <B>o_current</B> pointed object, it stores into the
707 * GSCHEM_TOPLEVEL structure the ....
708 * These variables are used in the grip process.
710 * The function first erases the grips.
712 * The coordinates of the selected corner are put in
713 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
715 * The coordinates of the opposite corner go in
716 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not
717 * suppose to change during the action.
719 * \param [in] w_current The GSCHEM_TOPLEVEL object.
720 * \param [in] o_current Picture OBJECT to check.
721 * \param [in] x (unused)
722 * \param [in] y (unused)
723 * \param [out] whichone Which coordinate to check.
725 static void o_grips_start_picture(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
726 int x, int y, int whichone)
728 TOPLEVEL *toplevel = w_current->toplevel;
729 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
731 w_current->current_pixbuf = o_picture_get_pixbuf (toplevel, o_current);
732 w_current->pixbuf_filename =
733 g_strdup (o_picture_get_filename (toplevel, o_current));
734 w_current->pixbuf_wh_ratio = o_picture_get_ratio (toplevel, o_current);
736 /* (second_wx,second_wy) is the selected corner */
737 /* (first_wx, first_wy) is the opposite corner */
738 switch(whichone) {
739 case PICTURE_UPPER_LEFT:
740 w_current->second_wx = o_current->picture->upper_x;
741 w_current->second_wy = o_current->picture->upper_y;
742 w_current->first_wx = o_current->picture->lower_x;
743 w_current->first_wy = o_current->picture->lower_y;
744 break;
745 case PICTURE_LOWER_RIGHT:
746 w_current->second_wx = o_current->picture->lower_x;
747 w_current->second_wy = o_current->picture->lower_y;
748 w_current->first_wx = o_current->picture->upper_x;
749 w_current->first_wy = o_current->picture->upper_y;
750 break;
751 case PICTURE_UPPER_RIGHT:
752 w_current->second_wx = o_current->picture->lower_x;
753 w_current->second_wy = o_current->picture->upper_y;
754 w_current->first_wx = o_current->picture->upper_x;
755 w_current->first_wy = o_current->picture->lower_y;
756 break;
757 case PICTURE_LOWER_LEFT:
758 w_current->second_wx = o_current->picture->upper_x;
759 w_current->second_wy = o_current->picture->lower_y;
760 w_current->first_wx = o_current->picture->lower_x;
761 w_current->first_wy = o_current->picture->upper_y;
762 break;
763 default:
764 return; /* error */
767 /* draw the first temporary picture */
768 /* o_picture_invalidate_rubber (w_current); */
769 w_current->rubber_visible = 1;
772 /*! \brief Initialize grip motion process for a circle.
773 * \par Function Description
774 * This function initializes the grip motion process for a circle.
775 * From the <B>o_current</B> pointed object, it stores into the
776 * GSCHEM_TOPLEVEL structure the coordinate of the center and the radius.
777 * These variables are used in the grip process.
779 * The function first erases the grips.
781 * The coordinates of the center are put in
782 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>). They are not suppose
783 * to change during the action.
785 * The radius of the circle is stored in <B>w_current->distance</B>.
787 * \param [in] w_current The GSCHEM_TOPLEVEL object.
788 * \param [in] o_current Circle OBJECT to check.
789 * \param [in] x (unused)
790 * \param [in] y (unused)
791 * \param [out] whichone Which coordinate to check.
793 static void o_grips_start_circle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
794 int x, int y, int whichone)
797 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
799 /* store circle center and radius in GSCHEM_TOPLEVEL structure */
800 w_current->first_wx = o_current->circle->center_x;
801 w_current->first_wy = o_current->circle->center_y;
802 w_current->distance = o_current->circle->radius;
804 /* draw the first temporary circle */
805 /* o_circle_invalidate_rubber (w_current); */
806 w_current->rubber_visible = 1;
809 /*! \brief Initialize grip motion process for a line.
810 * This function starts the move of one of the two grips of the line
811 * object <B>o_current</B>.
813 * During the move of the grip, the line is described by
814 * (<B>w_current->first_wx</B>,<B>w_current->first_wy</B>) and
815 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
817 * The line end that corresponds to the moving grip is in
818 * (<B>w_current->second_wx</B>,<B>w_current->second_wy</B>).
820 * \param [in] w_current The GSCHEM_TOPLEVEL object.
821 * \param [in] o_current Line OBJECT to check.
822 * \param [in] x (unused)
823 * \param [in] y (unused)
824 * \param [out] whichone Which coordinate to check.
826 static void o_grips_start_line(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
827 int x, int y, int whichone)
829 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE;
831 /* describe the line with GSCHEM_TOPLEVEL variables */
832 w_current->second_wx = o_current->line->x[whichone];
833 w_current->second_wy = o_current->line->y[whichone];
834 w_current->first_wx = o_current->line->x[!whichone];
835 w_current->first_wy = o_current->line->y[!whichone];
837 /* draw the first temporary line */
838 /* o_line_invalidate_rubber (w_current); */
839 w_current->rubber_visible = 1;
842 /*! \brief Start process of modifiying one grip.
843 * \par Function Description
844 * This function starts the process of modifying one grip of an object
845 * on the current sheet. The event occured in (<B>w_x</B>,<B>w_y</B>) in world unit.
846 * If this position is related to a grip of an object, the function
847 * prepares the modification of this grip thanks to the user input.
849 * The function returns <B>FALSE</B> if an error occured or if no grip
850 * have been found under (<B>w_x</B>,<B>w_y</B>). It returns <B>TRUE</B> if a grip
851 * has been found and modification of the object has been started.
853 * If a grip has been found, this function modifies the GSCHEM_TOPLEVEL
854 * variables <B>which_grip</B> and <B>which_object</B> with the identifier
855 * of the grip and the object it belongs to respectively.
857 * \param [in] w_current The GSCHEM_TOPLEVEL object.
858 * \param [in] w_x Current x coordinate of pointer in world units.
859 * \param [in] w_y Current y coordinate of pointer in world units.
860 * \return FALSE if an error occurred or no grip was found, TRUE otherwise.
862 int o_grips_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
864 OBJECT *object;
865 int whichone;
867 if (w_current->draw_grips == FALSE) {
868 return(FALSE);
871 /* search if there is a grip on a selected object at (w_x,w_y) */
872 object = o_grips_search_world(w_current, w_x, w_y, &whichone);
874 if (object == NULL)
875 return FALSE;
877 w_current->which_grip = whichone;
878 w_current->which_object = object;
880 /* Switch off drawing for the object being modified */
881 object->dont_redraw = TRUE;
882 o_invalidate (w_current, object);
884 /* there is one */
885 /* depending on its type, start the modification process */
886 switch(object->type) {
887 case(OBJ_ARC):
888 /* start the modification of a grip on an arc */
889 o_grips_start_arc(w_current, object, w_x, w_y, whichone);
890 return(TRUE);
892 case(OBJ_BOX):
893 /* start the modification of a grip on a box */
894 o_grips_start_box(w_current, object, w_x, w_y, whichone);
895 return(TRUE);
897 case(OBJ_PATH):
898 /* start the modification of a grip on a path */
899 o_grips_start_path(w_current, object, w_x, w_y, whichone);
900 return(TRUE);
902 case(OBJ_PICTURE):
903 /* start the modification of a grip on a picture */
904 o_grips_start_picture(w_current, object, w_x, w_y, whichone);
905 return(TRUE);
907 case(OBJ_CIRCLE):
908 /* start the modification of a grip on a circle */
909 o_grips_start_circle(w_current, object, w_x, w_y, whichone);
910 return(TRUE);
912 case(OBJ_LINE):
913 case(OBJ_NET):
914 case(OBJ_PIN):
915 case(OBJ_BUS):
916 /* identical for line/net/pin/bus */
917 /* start the modification of a grip on a line */
918 o_grips_start_line(w_current, object, w_x, w_y, whichone);
919 return(TRUE);
921 default:
922 /* object type unknown : error condition */
923 return(FALSE);
925 return(FALSE);
928 /*! \brief Modify previously selected object according to mouse position.
929 * \par Function Description
930 * This function modify the previously selected
931 * object according to the mouse position in <B>w_x</B> and <B>w_y</B>.
932 * The grip under modification is updated and the temporary object displayed.
934 * The object under modification is <B>w_current->which_object</B> and
935 * the grip concerned is <B>w_current->which_grip</B>.
937 * Depending on the object type, a specific function is used.
938 * It erases the temporary object, updates its internal representation,
939 * and draws it again.
941 * \param [in] w_current The GSCHEM_TOPLEVEL object.
942 * \param [in] w_x Current x coordinate of pointer in world units.
943 * \param [in] w_y Current y coordinate of pointer in world units.
945 void o_grips_motion(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y)
947 int grip = w_current->which_grip;
949 g_assert( w_current->inside_action != 0 );
950 g_return_if_fail( w_current->which_object != NULL );
952 switch(w_current->which_object->type) {
953 case OBJ_ARC:
954 o_arc_motion (w_current, w_x, w_y, grip);
955 break;
957 case OBJ_BOX:
958 o_box_motion (w_current, w_x, w_y);
959 break;
961 case OBJ_PATH:
962 o_path_motion (w_current, w_x, w_y);
963 break;
965 case OBJ_PICTURE:
966 o_picture_motion (w_current, w_x, w_y);
967 break;
969 case OBJ_CIRCLE:
970 o_circle_motion (w_current, w_x, w_y);
971 break;
973 case OBJ_LINE:
974 case OBJ_NET:
975 case OBJ_PIN:
976 case OBJ_BUS:
977 o_line_motion (w_current, w_x, w_y);
978 break;
980 default:
981 return; /* error condition */
986 /*! \brief Cancel process of modifying object with grip.
988 * \par Function Description
989 * This function cancels the process of modifying a parameter
990 * of an object with a grip. It's main utility is to reset the
991 * dont_redraw flag on the object which was being modified.
993 * \param [in,out] w_current The GSCHEM_TOPLEVEL object.
995 void o_grips_cancel(GSCHEM_TOPLEVEL *w_current)
997 OBJECT *object = w_current->which_object;
999 /* reset global variables */
1000 w_current->which_grip = -1;
1001 w_current->which_object = NULL;
1002 w_current->rubber_visible = 0;
1004 /* Switch drawing of the object back on */
1005 g_return_if_fail (object != NULL);
1006 object->dont_redraw = FALSE;
1010 /*! \brief End process of modifying arc object with grip.
1011 * \par Function Description
1012 * This function ends the grips process specific to an arc object. It erases
1013 * the old arc and write back to the object the new parameters of the arc.
1014 * Depending on the grip selected and moved, the right fields are updated.
1015 * The function handles the conversion from screen unit to world unit before
1016 * updating and redrawing.
1018 * If the grip at the center of the arc has been moved - modifying the radius
1019 * of the arc -, the new radius is calculated expressed in world unit
1020 * (the center is unchanged). It is updated with the function #o_arc_modify().
1022 * If one of the end of arc grip has been moved - modifying one of the
1023 * angles describing the arc -, this angle is updated with the
1024 * #o_arc_modify() function.
1026 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1027 * \param [in] o_current Arc OBJECT to end modification on.
1028 * \param [in] whichone Which grip is pointed to.
1030 static void o_grips_end_arc(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1031 int whichone)
1033 TOPLEVEL *toplevel = w_current->toplevel;
1034 int arg1, arg2;
1036 /* erase the temporary arc */
1037 /* o_arc_invalidate_rubber (w_current); */
1039 /* determination of the parameters to give to o_arc_modify() */
1040 switch(whichone) {
1041 case ARC_RADIUS:
1042 /* get the radius from w_current */
1043 arg1 = w_current->distance;
1044 /* second parameter is not used */
1045 arg2 = -1;
1046 break;
1048 case ARC_START_ANGLE:
1049 /* get the start angle from w_current */
1050 arg1 = w_current->second_wx;
1051 /* second parameter is not used */
1052 arg2 = -1;
1053 break;
1055 case ARC_END_ANGLE:
1056 /* get the end angle from w_current */
1057 arg1 = w_current->second_wy;
1058 /* second parameter is not used */
1059 arg2 = -1;
1060 break;
1062 default:
1063 return;
1066 /* modify the arc with the parameters determined above */
1067 o_arc_modify(toplevel, o_current, arg1, arg2, whichone);
1070 /*! \todo Finish function documentation!!!
1071 * \brief End process of modifying box object with grip.
1072 * \par Function Description
1074 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1075 * \param [in] o_current Box OBJECT to end modification on.
1076 * \param [in] whichone Which grip is pointed to.
1078 static void o_grips_end_box(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1079 int whichone)
1081 TOPLEVEL *toplevel = w_current->toplevel;
1082 int box_width, box_height;
1084 box_width = GET_BOX_WIDTH (w_current);
1085 box_height = GET_BOX_HEIGHT(w_current);
1087 /* don't allow zero width/height boxes
1088 * this ends the box drawing behavior
1089 * we want this? hack */
1090 if ((box_width == 0) || (box_height == 0)) {
1091 o_box_invalidate_rubber (w_current);
1092 o_invalidate (w_current, o_current);
1093 return;
1096 o_box_modify(toplevel, o_current, w_current->second_wx, w_current->second_wy, whichone);
1099 /*! \todo Finish function documentation!!!
1100 * \brief End process of modifying path object with grip.
1101 * \par Function Description
1103 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1104 * \param [in] o_current Picture OBJECT to end modification on.
1105 * \param [in] whichone Which grip is pointed to.
1107 static void o_grips_end_path(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1108 int whichone)
1110 o_path_modify (w_current->toplevel, o_current,
1111 w_current->second_wx, w_current->second_wy, whichone);
1114 /*! \todo Finish function documentation!!!
1115 * \brief End process of modifying picture object with grip.
1116 * \par Function Description
1118 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1119 * \param [in] o_current Picture OBJECT to end modification on.
1120 * \param [in] whichone Which grip is pointed to.
1122 static void o_grips_end_picture(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1123 int whichone)
1125 TOPLEVEL *toplevel = w_current->toplevel;
1127 /* don't allow zero width/height picturees
1128 * this ends the picture drawing behavior
1129 * we want this? hack */
1130 if ((GET_PICTURE_WIDTH(w_current) == 0) || (GET_PICTURE_HEIGHT(w_current) == 0)) {
1131 o_picture_invalidate_rubber (w_current);
1132 o_invalidate (w_current, o_current);
1133 return;
1136 o_picture_modify(toplevel, o_current,
1137 w_current->second_wx, w_current->second_wy, whichone);
1139 g_object_unref (w_current->current_pixbuf);
1140 w_current->current_pixbuf = NULL;
1141 g_free (w_current->pixbuf_filename);
1142 w_current->pixbuf_filename = NULL;
1143 w_current->pixbuf_wh_ratio = 0;
1146 /*! \brief End process of modifying circle object with grip.
1147 * \par Function Description
1148 * This function ends the process of modifying the radius of the circle
1149 * object <B>*o_current</B>.
1150 * The modified circle is finally normally drawn.
1152 * A circle with a null radius is not allowed. In this case, the process
1153 * is stopped and the circle is left unchanged.
1155 * The last value of the radius is in <B>w_current->distance</B> in screen units.
1157 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1158 * \param [in] o_current Circle OBJECT to end modification on.
1159 * \param [in] whichone Which grip is pointed to.
1161 static void o_grips_end_circle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1162 int whichone)
1164 TOPLEVEL *toplevel = w_current->toplevel;
1166 /* don't allow zero radius circles
1167 * this ends the circle drawing behavior
1168 * we want this? hack */
1169 if (w_current->distance == 0) {
1170 o_circle_invalidate_rubber (w_current);
1171 o_invalidate (w_current, o_current);
1172 return;
1175 /* modify the radius of the circle */
1176 o_circle_modify(toplevel, o_current, w_current->distance, -1, CIRCLE_RADIUS);
1179 /*! \brief End process of modifying line object with grip.
1180 * \par Function Description
1181 * This function ends the process of modifying one end of the line
1182 * object <B>*o_current</B>.
1183 * This end is identified by <B>whichone</B>. The line object is modified
1184 * according to the <B>whichone</B> parameter and the last position of the
1185 * line end.
1186 * The modified line is finally normally drawn.
1188 * A line with a null width, i.e. when both ends are identical, is not
1189 * allowed. In this case, the process is stopped and the line unchanged.
1191 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1192 * \param [in] o_current Line OBJECT to end modification on.
1193 * \param [in] whichone Which grip is pointed to.
1195 static void o_grips_end_line(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1196 int whichone)
1198 TOPLEVEL *toplevel = w_current->toplevel;
1200 /* don't allow zero length nets / lines / pins
1201 * this ends the net drawing behavior
1202 * we want this? hack */
1203 if ((w_current->first_wx == w_current->second_wx) &&
1204 (w_current->first_wy == w_current->second_wy)) {
1205 o_box_invalidate_rubber (w_current);
1206 o_invalidate (w_current, o_current);
1207 return;
1210 /* modify the right line end according to whichone */
1211 o_line_modify(toplevel, o_current,
1212 w_current->second_wx, w_current->second_wy, whichone);
1216 /*! \brief End process of modifying net object with grip.
1217 * \par Function Description
1218 * This function ends the process of modifying one end of the net
1219 * object <B>*o_current</B>.
1220 * This end is identified by <B>whichone</B>. The line object is modified
1221 * according to the <B>whichone</B> parameter and the last position of the
1222 * line end.
1223 * The connections to the modified net are checked and recreated if neccessary.
1225 * A net with zero length, i.e. when both ends are identical, is not
1226 * allowed. In this case, the process is stopped and the line unchanged.
1228 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1229 * \param [in] o_current Net OBJECT to end modification on.
1230 * \param [in] whichone Which grip is pointed to.
1232 static void o_grips_end_net(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1233 int whichone)
1235 TOPLEVEL *toplevel = w_current->toplevel;
1236 GList *connected_objects;
1238 /* don't allow zero length net
1239 * this ends the net drawing behavior
1240 * we want this? hack */
1241 if ((w_current->first_wx == w_current->second_wx) &&
1242 (w_current->first_wy == w_current->second_wy)) {
1243 o_invalidate (w_current, o_current);
1244 return;
1247 s_conn_remove_object (toplevel, o_current);
1248 o_net_modify (toplevel, o_current, w_current->second_wx,
1249 w_current->second_wy, w_current->which_grip);
1250 s_conn_update_object (toplevel, o_current);
1252 /* add bus rippers if necessary */
1253 connected_objects = s_conn_return_others (NULL, o_current);
1254 o_net_add_busrippers (w_current, o_current, connected_objects);
1255 g_list_free (connected_objects);
1258 /*! \brief End process of modifying pin object with grip.
1259 * \par Function Description
1260 * This function ends the process of modifying one end of the pin
1261 * object <B>*o_current</B>.
1262 * This end is identified by <B>whichone</B>. The pin object is modified
1263 * according to the <B>whichone</B> parameter and the last position of the
1264 * pin end.
1265 * The connections to the modified pin are checked and recreated if neccessary.
1267 * A pin with zero length, i.e. when both ends are identical, is not
1268 * allowed. In this case, the process is stopped and the line unchanged.
1270 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1271 * \param [in] o_current Net OBJECT to end modification on.
1272 * \param [in] whichone Which grip is pointed to.
1274 static void o_grips_end_pin(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1275 int whichone)
1277 TOPLEVEL *toplevel = w_current->toplevel;
1279 /* don't allow zero length pin
1280 * this ends the pin changing behavior
1281 * we want this? hack */
1282 if ((w_current->first_wx == w_current->second_wx) &&
1283 (w_current->first_wy == w_current->second_wy)) {
1284 o_invalidate (w_current, o_current);
1285 return;
1288 s_conn_remove_object (toplevel, o_current);
1289 o_pin_modify (toplevel, o_current, w_current->second_wx,
1290 w_current->second_wy, w_current->which_grip);
1291 s_conn_update_object (toplevel, o_current);
1294 /*! \brief End process of modifying bus object with grip.
1295 * \par Function Description
1296 * This function ends the process of modifying one end of the bus
1297 * object <B>*o_current</B>.
1298 * This end is identified by <B>whichone</B>. The line object is modified
1299 * according to the <B>whichone</B> parameter and the last position of the
1300 * bus end.
1301 * The connections to the modified bus are checked and recreated if neccessary.
1303 * A bus with zero length, i.e. when both ends are identical, is not
1304 * allowed. In this case, the process is stopped and the bus unchanged.
1306 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1307 * \param [in] o_current bus OBJECT to end modification on.
1308 * \param [in] whichone Which grip is pointed to.
1310 static void o_grips_end_bus(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current,
1311 int whichone)
1313 TOPLEVEL *toplevel = w_current->toplevel;
1315 /* don't allow zero length bus
1316 * this ends the bus changing behavior
1317 * we want this? hack */
1318 if ((w_current->first_wx == w_current->second_wx) &&
1319 (w_current->first_wy == w_current->second_wy)) {
1320 o_invalidate (w_current, o_current);
1321 return;
1324 s_conn_remove_object (toplevel, o_current);
1325 o_bus_modify (toplevel, o_current, w_current->second_wx,
1326 w_current->second_wy, w_current->which_grip);
1327 s_conn_update_object (toplevel, o_current);
1331 /*! \brief End process of modifying object with grip.
1332 * \par Function Description
1333 * This function ends the process of modifying a parameter of an object
1334 * with a grip.
1335 * The temporary representation of the object is erased, the object is
1336 * modified and finally drawn.
1338 * The object under modification is <B>w_current->which_object</B> and
1339 * the grip concerned is <B>w_current->which_grip</B>.
1341 * Depending on the object type, a specific function is used. It erases
1342 * the temporary object, updates the object and draws the modified object
1343 * normally.
1345 * \param [in,out] w_current The GSCHEM_TOPLEVEL object.
1347 void o_grips_end(GSCHEM_TOPLEVEL *w_current)
1349 TOPLEVEL *toplevel = w_current->toplevel;
1350 OBJECT *object;
1351 int grip;
1353 object = w_current->which_object;
1354 grip = w_current->which_grip;
1356 if (!object) {
1357 /* actually this is an error condition hack */
1358 w_current->inside_action = 0;
1359 i_set_state(w_current, SELECT);
1360 return;
1363 switch(object->type) {
1365 case(OBJ_ARC):
1366 /* modify an arc object */
1367 o_grips_end_arc(w_current, object, grip);
1368 break;
1370 case(OBJ_BOX):
1371 /* modify a box object */
1372 o_grips_end_box(w_current, object, grip);
1373 break;
1375 case(OBJ_PATH):
1376 /* modify a path object */
1377 o_grips_end_path(w_current, object, grip);
1378 break;
1380 case(OBJ_PICTURE):
1381 /* modify a picture object */
1382 o_grips_end_picture(w_current, object, grip);
1383 break;
1385 case(OBJ_CIRCLE):
1386 /* modify a circle object */
1387 o_grips_end_circle(w_current, object, grip);
1388 break;
1390 case(OBJ_LINE):
1391 /* modify a line object */
1392 o_grips_end_line(w_current, object, grip);
1393 break;
1395 case(OBJ_NET):
1396 /* modify a net object */
1397 o_grips_end_net(w_current, object, grip);
1398 break;
1400 case(OBJ_PIN):
1401 /* modify a pin object */
1402 o_grips_end_pin(w_current, object, grip);
1403 break;
1405 case(OBJ_BUS):
1406 /* modify a bus object */
1407 o_grips_end_bus(w_current, object, grip);
1408 break;
1410 default:
1411 return;
1414 /* Switch drawing of the object back on */
1415 object->dont_redraw = FALSE;
1416 o_invalidate (w_current, object);
1418 /* reset global variables */
1419 w_current->which_grip = -1;
1420 w_current->which_object = NULL;
1422 w_current->rubber_visible = 0;
1424 toplevel->page_current->CHANGED=1;
1425 o_undo_savestate(w_current, UNDO_ALL);
1429 /*! \brief Get half the width and height of grip in screen units.
1430 * \par Function Description
1431 * According to the current zoom level, the function returns half the width
1432 * and height of a grip in screen units.
1434 * <B>GRIP_SIZE1</B> and <B>GRIP_SIZE2</B> and <B>GRIP_SIZE3</B> are macros defined
1435 * in gschem_defines.h. They are the half width/height of a grip in
1436 * world unit for a determined range of zoom factors.
1438 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1439 * \return Half grip size in screen units.
1441 int o_grips_size(GSCHEM_TOPLEVEL *w_current)
1443 TOPLEVEL *toplevel = w_current->toplevel;
1444 int factor, size;
1446 factor = (int) toplevel->page_current->to_world_x_constant;
1447 if (factor > SMALL_ZOOMFACTOR1) {
1448 /* big zoom factor : small size converted to screen unit */
1449 size = SCREENabs (w_current, GRIP_SIZE1);
1450 } else if (factor > SMALL_ZOOMFACTOR2) {
1451 /* medium zoom factor : medium size converted to screen unit */
1452 size = SCREENabs (w_current, GRIP_SIZE2);
1453 } else {
1454 /* small zoom factor : big size converted to screen unit */
1455 size = SCREENabs (w_current, GRIP_SIZE3);
1458 return min(size, MAXIMUM_GRIP_PIXELS/2);
1461 /*! \brief Draw grip centered at <B>x</B>, <B>y</B>
1462 * \par Function Description
1463 * This function draws a grip centered at (<B>x</B>,<B>y</B>). Its color is
1464 * either the selection color or the overriding color from
1465 * <B>toplevel->override_color</B>.
1467 * The size of the grip depends on the current zoom factor.
1469 * <B>x</B> and <B>y</B> are in screen unit.
1471 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1472 * \param [in] wx Center x world coordinate for drawing grip.
1473 * \param [in] wy Center y world coordinate for drawing grip.
1475 void o_grips_draw(GSCHEM_TOPLEVEL *w_current, int wx, int wy)
1477 TOPLEVEL *toplevel = w_current->toplevel;
1478 int color;
1479 int size, w_size;
1482 * Depending on the current zoom level, the size of the grip is
1483 * determined. <B>size</B> is half the width and height of the grip.
1485 /* size is half the width of grip */
1486 size = o_grips_size (w_current);
1487 w_size = WORLDabs (w_current, size);
1490 * The grip can be displayed or erased : if <B>toplevel->override_color</B>
1491 * is not set the grip is drawn with the selection color ; if
1492 * <B>toplevel->override_color</B> is set then the color it refers it
1493 * is used. This way the grip can be erased if this color is the
1494 * background color.
1496 if (toplevel->override_color != -1 ) {
1497 /* override : use the override_color instead */
1498 color = toplevel->override_color;
1499 } else {
1500 /* use the normal selection color */
1501 color = SELECT_COLOR;
1504 /* You can only tell an offset of the grip when it is very small,
1505 * at which point, the object it's on is probably drawn 1px wide.
1506 * Pass 0 as a hint that we're centering on a "hardware" line.
1508 gschem_cairo_center_box (w_current, 0, 0, wx, wy, w_size, w_size);
1510 gschem_cairo_set_source_color (w_current, x_color_lookup (color));
1511 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1);
1515 /*! \brief Draw objects being grip maniuplated from GSCHEM_TOPLEVEL object.
1517 * \par Function Description
1518 * This function draws the objects being grip manipulated.
1520 * \param [in] w_current The GSCHEM_TOPLEVEL object.
1522 void o_grips_draw_rubber (GSCHEM_TOPLEVEL *w_current)
1524 g_return_if_fail (w_current->which_object != NULL);
1526 switch(w_current->which_object->type) {
1527 case OBJ_ARC:
1528 o_arc_draw_rubber (w_current);
1529 break;
1531 case OBJ_BOX:
1532 o_box_draw_rubber (w_current);
1533 break;
1535 case OBJ_PATH:
1536 o_path_draw_rubber (w_current);
1537 break;
1539 case OBJ_PICTURE:
1540 o_picture_draw_rubber (w_current);
1541 break;
1543 case OBJ_CIRCLE:
1544 o_circle_draw_rubber (w_current);
1545 break;
1547 case OBJ_LINE:
1548 case OBJ_NET:
1549 case OBJ_PIN:
1550 case OBJ_BUS:
1551 o_line_draw_rubber (w_current);
1552 break;
1554 default:
1555 return; /* error condition */