gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2010 gEDA Contributors (see ChangeLog for details) 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 #include <config.h> 00021 00022 #include <stdio.h> 00023 #include <math.h> 00024 00025 #include "gschem.h" 00026 00027 #ifdef HAVE_LIBDMALLOC 00028 #include <dmalloc.h> 00029 #endif 00030 00031 #define GET_BOX_WIDTH(w) abs((w)->second_wx - (w)->first_wx) 00032 #define GET_BOX_HEIGHT(w) abs((w)->second_wy - (w)->first_wy) 00033 00034 #define GET_PICTURE_WIDTH(w) \ 00035 abs((w)->second_wx - (w)->first_wx) 00036 #define GET_PICTURE_HEIGHT(w) \ 00037 (w)->pixbuf_wh_ratio == 0 ? 0 : abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio 00038 #define GET_PICTURE_LEFT(w) \ 00039 min((w)->first_wx, (w)->second_wx) 00040 #define GET_PICTURE_TOP(w) \ 00041 (w)->first_wy > (w)->second_wy ? (w)->first_wy : \ 00042 (w)->first_wy+abs((w)->second_wx - (w)->first_wx)/(w)->pixbuf_wh_ratio 00043 00044 00067 OBJECT *o_grips_search_world(GSCHEM_TOPLEVEL *w_current, int x, int y, int *whichone) 00068 { 00069 TOPLEVEL *toplevel = w_current->toplevel; 00070 OBJECT *object=NULL; 00071 OBJECT *found=NULL; 00072 GList *s_current; 00073 int size; 00074 int w_size; 00075 00076 if (!whichone) { 00077 return(NULL); 00078 } 00079 00080 /* get the size of the grip according to zoom level */ 00081 size = o_grips_size(w_current); 00082 w_size = WORLDabs (w_current, size ); 00083 00084 s_current = geda_list_get_glist( toplevel->page_current->selection_list ); 00085 while (s_current != NULL) { 00086 object = (OBJECT *) s_current->data; 00087 if (object) { 00088 switch(object->type) { 00089 case(OBJ_ARC): 00090 /* check the grips of the arc object */ 00091 found = o_grips_search_arc_world(w_current, object, 00092 x, y, w_size, whichone); 00093 if(found != NULL) return found; 00094 break; 00095 00096 case(OBJ_BOX): 00097 /* check the grips of the box object */ 00098 found = o_grips_search_box_world(w_current, object, 00099 x, y, w_size, whichone); 00100 if(found != NULL) return found; 00101 break; 00102 00103 case(OBJ_PATH): 00104 /* check the grips of the path object */ 00105 found = o_grips_search_path_world(w_current, object, 00106 x, y, w_size, whichone); 00107 if(found != NULL) return found; 00108 break; 00109 00110 case(OBJ_PICTURE): 00111 /* check the grips of the picture object */ 00112 found = o_grips_search_picture_world(w_current, object, 00113 x, y, w_size, whichone); 00114 if(found != NULL) return found; 00115 break; 00116 00117 case(OBJ_CIRCLE): 00118 /* check the grips of the circle object */ 00119 found = o_grips_search_circle_world(w_current, object, 00120 x, y, w_size, whichone); 00121 if(found != NULL) return found; 00122 break; 00123 00124 case(OBJ_LINE): 00125 case(OBJ_PIN): 00126 case(OBJ_NET): 00127 case(OBJ_BUS): 00128 /* check the grips of the line object */ 00129 /* the function is the same for line, pin, net, bus */ 00130 found = o_grips_search_line_world(w_current, object, 00131 x, y, w_size, whichone); 00132 if(found != NULL) return found; 00133 break; 00134 00135 default: 00136 break; 00137 } 00138 } 00139 s_current = g_list_next(s_current); 00140 } 00141 00142 return(NULL); 00143 } 00144 00145 00159 static gboolean inside_grip( int x, int y, int grip_x, int grip_y, int size ) 00160 { 00161 int xmin, ymin, xmax, ymax; 00162 00163 xmin = grip_x - size; 00164 ymin = grip_y - size; 00165 xmax = xmin + 2 * size; 00166 ymax = ymin + 2 * size; 00167 00168 return inside_region(xmin, ymin, xmax, ymax, x, y); 00169 } 00170 00206 OBJECT *o_grips_search_arc_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00207 int x, int y, int size, int *whichone) 00208 { 00209 int centerx, centery, radius, start_angle, end_angle; 00210 double tmp; 00211 00212 centerx = o_current->arc->x; 00213 centery = o_current->arc->y; 00214 radius = o_current->arc->width / 2; 00215 start_angle = o_current->arc->start_angle; 00216 end_angle = o_current->arc->end_angle; 00217 00218 /* check the grip on the center of the arc */ 00219 if (inside_grip(x, y, centerx, centery, size)) { 00220 *whichone = ARC_RADIUS; 00221 return(o_current); 00222 } 00223 00224 /* check the grip at the end angle of the arc */ 00225 tmp = ((double) start_angle + end_angle) * M_PI / 180; 00226 if (inside_grip(x, y, 00227 centerx + radius * cos(tmp), 00228 centery + radius * sin(tmp), size)) { 00229 *whichone = ARC_END_ANGLE; 00230 return(o_current); 00231 } 00232 00233 /* check the grip at the start angle of the arc */ 00234 tmp = ((double) start_angle) * M_PI / 180; 00235 if (inside_grip(x, y, 00236 centerx + radius * cos(tmp), 00237 centery + radius * sin(tmp), size)) { 00238 *whichone = ARC_START_ANGLE; 00239 return(o_current); 00240 } 00241 00242 return NULL; 00243 } 00244 00271 OBJECT *o_grips_search_box_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00272 int x, int y, int size, int *whichone) 00273 { 00274 /* inside upper left grip ? */ 00275 if (inside_grip(x, y, 00276 o_current->box->upper_x, 00277 o_current->box->upper_y, size)) { 00278 *whichone = BOX_UPPER_LEFT; 00279 return(o_current); 00280 } 00281 00282 /* inside lower right grip ? */ 00283 if (inside_grip(x, y, 00284 o_current->box->lower_x, 00285 o_current->box->lower_y, size)) { 00286 *whichone = BOX_LOWER_RIGHT; 00287 return(o_current); 00288 } 00289 00290 /* inside upper right grip ? */ 00291 if (inside_grip(x, y, 00292 o_current->box->lower_x, 00293 o_current->box->upper_y, size)) { 00294 *whichone = BOX_UPPER_RIGHT; 00295 return(o_current); 00296 } 00297 00298 /* inside lower left grip ? */ 00299 if (inside_grip(x, y, 00300 o_current->box->upper_x, 00301 o_current->box->lower_y, size)) { 00302 *whichone = BOX_LOWER_LEFT; 00303 return(o_current); 00304 } 00305 00306 return NULL; 00307 } 00308 00336 OBJECT *o_grips_search_path_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00337 int x, int y, int size, int *whichone) 00338 { 00339 PATH_SECTION *section; 00340 int i; 00341 int grip_no = 0; 00342 00343 for (i = 0; i < o_current->path->num_sections; i++) { 00344 section = &o_current->path->sections[i]; 00345 00346 switch (section->code) { 00347 case PATH_CURVETO: 00348 /* inside first control grip ? */ 00349 if (inside_grip(x, y, section->x1, section->y1, size)) { 00350 *whichone = grip_no; 00351 return o_current; 00352 } 00353 grip_no ++; 00354 /* inside second control grip ? */ 00355 if (inside_grip(x, y, section->x2, section->y2, size)) { 00356 *whichone = grip_no; 00357 return o_current; 00358 } 00359 grip_no ++; 00360 /* Fall through */ 00361 case PATH_MOVETO: 00362 case PATH_MOVETO_OPEN: 00363 case PATH_LINETO: 00364 /* inside destination control grip ? */ 00365 if (inside_grip(x, y, section->x3, section->y3, size)) { 00366 *whichone = grip_no; 00367 return o_current; 00368 } 00369 grip_no ++; 00370 break; 00371 case PATH_END: 00372 break; 00373 } 00374 } 00375 00376 return NULL; 00377 } 00378 00406 OBJECT *o_grips_search_picture_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00407 int x, int y, int size, int *whichone) 00408 { 00409 /* inside upper left grip ? */ 00410 if (inside_grip(x, y, 00411 o_current->picture->upper_x, 00412 o_current->picture->upper_y, size)) { 00413 *whichone = PICTURE_UPPER_LEFT; 00414 return(o_current); 00415 } 00416 00417 /* inside lower right grip ? */ 00418 if (inside_grip(x, y, 00419 o_current->picture->lower_x, 00420 o_current->picture->lower_y, size)) { 00421 *whichone = PICTURE_LOWER_RIGHT; 00422 return(o_current); 00423 } 00424 00425 /* inside upper right grip ? */ 00426 if (inside_grip(x, y, 00427 o_current->picture->lower_x, 00428 o_current->picture->upper_y, size)) { 00429 *whichone = PICTURE_UPPER_RIGHT; 00430 return(o_current); 00431 } 00432 00433 /* inside lower left grip ? */ 00434 if (inside_grip(x, y, 00435 o_current->picture->upper_x, 00436 o_current->picture->lower_y, size)) { 00437 *whichone = PICTURE_LOWER_LEFT; 00438 return(o_current); 00439 } 00440 00441 return NULL; 00442 } 00443 00469 OBJECT *o_grips_search_circle_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00470 int x, int y, int size, int *whichone) 00471 { 00472 /* check the grip for radius */ 00473 if (inside_grip(x, y, 00474 o_current->circle->center_x + o_current->circle->radius, 00475 o_current->circle->center_y - o_current->circle->radius, 00476 size)) { 00477 *whichone = CIRCLE_RADIUS; 00478 return(o_current); 00479 } 00480 00481 return NULL; 00482 } 00483 00504 OBJECT *o_grips_search_line_world(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00505 int x, int y, int size, int *whichone) 00506 { 00507 /* check the grip on the end of line 1 */ 00508 if (inside_grip(x, y, 00509 o_current->line->x[LINE_END1], 00510 o_current->line->y[LINE_END1], size)) { 00511 *whichone = LINE_END1; 00512 return(o_current); 00513 } 00514 00515 /* check the grip on the end of line 2 */ 00516 if (inside_grip(x, y, 00517 o_current->line->x[LINE_END2], 00518 o_current->line->y[LINE_END2], size)) { 00519 *whichone = LINE_END2; 00520 return(o_current); 00521 } 00522 00523 return NULL; 00524 } 00525 00551 static void o_grips_start_arc(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00552 int x, int y, int whichone) 00553 { 00554 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE; 00555 00556 /* describe the arc with GSCHEM_TOPLEVEL variables */ 00557 /* center */ 00558 w_current->first_wx = o_current->arc->x; 00559 w_current->first_wy = o_current->arc->y; 00560 /* radius */ 00561 w_current->distance = o_current->arc->width / 2; 00562 /* angles */ 00563 w_current->second_wx = o_current->arc->start_angle; 00564 w_current->second_wy = o_current->arc->end_angle; 00565 00566 /* draw the first temporary arc */ 00567 /* o_arc_invalidate_rubber (w_current); */ 00568 w_current->rubber_visible = 1; 00569 } 00570 00592 static void o_grips_start_box(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00593 int x, int y, int whichone) 00594 { 00595 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE; 00596 00597 /* (second_wx, second_wy) is the selected corner */ 00598 /* (first_wx, first_wy) is the opposite corner */ 00599 switch(whichone) { 00600 case BOX_UPPER_LEFT: 00601 w_current->second_wx = o_current->box->upper_x; 00602 w_current->second_wy = o_current->box->upper_y; 00603 w_current->first_wx = o_current->box->lower_x; 00604 w_current->first_wy = o_current->box->lower_y; 00605 break; 00606 case BOX_LOWER_RIGHT: 00607 w_current->second_wx = o_current->box->lower_x; 00608 w_current->second_wy = o_current->box->lower_y; 00609 w_current->first_wx = o_current->box->upper_x; 00610 w_current->first_wy = o_current->box->upper_y; 00611 break; 00612 case BOX_UPPER_RIGHT: 00613 w_current->second_wx = o_current->box->lower_x; 00614 w_current->second_wy = o_current->box->upper_y; 00615 w_current->first_wx = o_current->box->upper_x; 00616 w_current->first_wy = o_current->box->lower_y; 00617 break; 00618 case BOX_LOWER_LEFT: 00619 w_current->second_wx = o_current->box->upper_x; 00620 w_current->second_wy = o_current->box->lower_y; 00621 w_current->first_wx = o_current->box->lower_x; 00622 w_current->first_wy = o_current->box->upper_y; 00623 break; 00624 default: 00625 return; /* error */ 00626 } 00627 00628 /* draw the first temporary box */ 00629 /* o_box_invalidate_rubber (w_current); */ 00630 w_current->rubber_visible = 1; 00631 } 00632 00655 static void o_grips_start_path(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00656 int x, int y, int whichone) 00657 { 00658 PATH_SECTION *section; 00659 int i; 00660 int grip_no = 0; 00661 int gx = -1; 00662 int gy = -1; 00663 00664 w_current->last_drawb_mode = -1; 00665 00666 for (i = 0; i < o_current->path->num_sections; i++) { 00667 section = &o_current->path->sections[i]; 00668 00669 switch (section->code) { 00670 case PATH_CURVETO: 00671 /* Two control point grips */ 00672 if (whichone == grip_no++) { 00673 gx = section->x1; 00674 gy = section->y1; 00675 } 00676 if (whichone == grip_no++) { 00677 gx = section->x2; 00678 gy = section->y2; 00679 } 00680 /* Fall through */ 00681 case PATH_MOVETO: 00682 case PATH_MOVETO_OPEN: 00683 case PATH_LINETO: 00684 /* Destination point grip */ 00685 if (whichone == grip_no++) { 00686 gx = section->x3; 00687 gy = section->y3; 00688 } 00689 break; 00690 case PATH_END: 00691 break; 00692 } 00693 } 00694 00695 w_current->first_wx = w_current->second_wx = gx; 00696 w_current->first_wy = w_current->second_wy = gy; 00697 00698 /* draw the first temporary path */ 00699 /* o_path_invalidate_rubber (w_current); */ 00700 w_current->rubber_visible = 1; 00701 } 00702 00725 static void o_grips_start_picture(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00726 int x, int y, int whichone) 00727 { 00728 TOPLEVEL *toplevel = w_current->toplevel; 00729 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE; 00730 00731 w_current->current_pixbuf = o_picture_get_pixbuf (toplevel, o_current); 00732 w_current->pixbuf_filename = 00733 g_strdup (o_picture_get_filename (toplevel, o_current)); 00734 w_current->pixbuf_wh_ratio = o_picture_get_ratio (toplevel, o_current); 00735 00736 /* (second_wx,second_wy) is the selected corner */ 00737 /* (first_wx, first_wy) is the opposite corner */ 00738 switch(whichone) { 00739 case PICTURE_UPPER_LEFT: 00740 w_current->second_wx = o_current->picture->upper_x; 00741 w_current->second_wy = o_current->picture->upper_y; 00742 w_current->first_wx = o_current->picture->lower_x; 00743 w_current->first_wy = o_current->picture->lower_y; 00744 break; 00745 case PICTURE_LOWER_RIGHT: 00746 w_current->second_wx = o_current->picture->lower_x; 00747 w_current->second_wy = o_current->picture->lower_y; 00748 w_current->first_wx = o_current->picture->upper_x; 00749 w_current->first_wy = o_current->picture->upper_y; 00750 break; 00751 case PICTURE_UPPER_RIGHT: 00752 w_current->second_wx = o_current->picture->lower_x; 00753 w_current->second_wy = o_current->picture->upper_y; 00754 w_current->first_wx = o_current->picture->upper_x; 00755 w_current->first_wy = o_current->picture->lower_y; 00756 break; 00757 case PICTURE_LOWER_LEFT: 00758 w_current->second_wx = o_current->picture->upper_x; 00759 w_current->second_wy = o_current->picture->lower_y; 00760 w_current->first_wx = o_current->picture->lower_x; 00761 w_current->first_wy = o_current->picture->upper_y; 00762 break; 00763 default: 00764 return; /* error */ 00765 } 00766 00767 /* draw the first temporary picture */ 00768 /* o_picture_invalidate_rubber (w_current); */ 00769 w_current->rubber_visible = 1; 00770 } 00771 00793 static void o_grips_start_circle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00794 int x, int y, int whichone) 00795 { 00796 00797 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE; 00798 00799 /* store circle center and radius in GSCHEM_TOPLEVEL structure */ 00800 w_current->first_wx = o_current->circle->center_x; 00801 w_current->first_wy = o_current->circle->center_y; 00802 w_current->distance = o_current->circle->radius; 00803 00804 /* draw the first temporary circle */ 00805 /* o_circle_invalidate_rubber (w_current); */ 00806 w_current->rubber_visible = 1; 00807 } 00808 00826 static void o_grips_start_line(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 00827 int x, int y, int whichone) 00828 { 00829 w_current->last_drawb_mode = LAST_DRAWB_MODE_NONE; 00830 00831 /* describe the line with GSCHEM_TOPLEVEL variables */ 00832 w_current->second_wx = o_current->line->x[whichone]; 00833 w_current->second_wy = o_current->line->y[whichone]; 00834 w_current->first_wx = o_current->line->x[!whichone]; 00835 w_current->first_wy = o_current->line->y[!whichone]; 00836 00837 /* draw the first temporary line */ 00838 /* o_line_invalidate_rubber (w_current); */ 00839 w_current->rubber_visible = 1; 00840 } 00841 00862 int o_grips_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00863 { 00864 OBJECT *object; 00865 int whichone; 00866 00867 if (w_current->draw_grips == FALSE) { 00868 return(FALSE); 00869 } 00870 00871 /* search if there is a grip on a selected object at (w_x,w_y) */ 00872 object = o_grips_search_world(w_current, w_x, w_y, &whichone); 00873 00874 if (object == NULL) 00875 return FALSE; 00876 00877 w_current->which_grip = whichone; 00878 w_current->which_object = object; 00879 00880 /* Switch off drawing for the object being modified */ 00881 object->dont_redraw = TRUE; 00882 o_invalidate (w_current, object); 00883 00884 /* there is one */ 00885 /* depending on its type, start the modification process */ 00886 switch(object->type) { 00887 case(OBJ_ARC): 00888 /* start the modification of a grip on an arc */ 00889 o_grips_start_arc(w_current, object, w_x, w_y, whichone); 00890 return(TRUE); 00891 00892 case(OBJ_BOX): 00893 /* start the modification of a grip on a box */ 00894 o_grips_start_box(w_current, object, w_x, w_y, whichone); 00895 return(TRUE); 00896 00897 case(OBJ_PATH): 00898 /* start the modification of a grip on a path */ 00899 o_grips_start_path(w_current, object, w_x, w_y, whichone); 00900 return(TRUE); 00901 00902 case(OBJ_PICTURE): 00903 /* start the modification of a grip on a picture */ 00904 o_grips_start_picture(w_current, object, w_x, w_y, whichone); 00905 return(TRUE); 00906 00907 case(OBJ_CIRCLE): 00908 /* start the modification of a grip on a circle */ 00909 o_grips_start_circle(w_current, object, w_x, w_y, whichone); 00910 return(TRUE); 00911 00912 case(OBJ_LINE): 00913 case(OBJ_NET): 00914 case(OBJ_PIN): 00915 case(OBJ_BUS): 00916 /* identical for line/net/pin/bus */ 00917 /* start the modification of a grip on a line */ 00918 o_grips_start_line(w_current, object, w_x, w_y, whichone); 00919 return(TRUE); 00920 00921 default: 00922 /* object type unknown : error condition */ 00923 return(FALSE); 00924 } 00925 return(FALSE); 00926 } 00927 00945 void o_grips_motion(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00946 { 00947 int grip = w_current->which_grip; 00948 00949 g_assert( w_current->inside_action != 0 ); 00950 g_return_if_fail( w_current->which_object != NULL ); 00951 00952 switch(w_current->which_object->type) { 00953 case OBJ_ARC: 00954 o_arc_motion (w_current, w_x, w_y, grip); 00955 break; 00956 00957 case OBJ_BOX: 00958 o_box_motion (w_current, w_x, w_y); 00959 break; 00960 00961 case OBJ_PATH: 00962 o_path_motion (w_current, w_x, w_y); 00963 break; 00964 00965 case OBJ_PICTURE: 00966 o_picture_motion (w_current, w_x, w_y); 00967 break; 00968 00969 case OBJ_CIRCLE: 00970 o_circle_motion (w_current, w_x, w_y); 00971 break; 00972 00973 case OBJ_LINE: 00974 case OBJ_NET: 00975 case OBJ_PIN: 00976 case OBJ_BUS: 00977 o_line_motion (w_current, w_x, w_y); 00978 break; 00979 00980 default: 00981 return; /* error condition */ 00982 } 00983 } 00984 00985 00995 void o_grips_cancel(GSCHEM_TOPLEVEL *w_current) 00996 { 00997 OBJECT *object = w_current->which_object; 00998 00999 /* reset global variables */ 01000 w_current->which_grip = -1; 01001 w_current->which_object = NULL; 01002 w_current->rubber_visible = 0; 01003 01004 /* Switch drawing of the object back on */ 01005 g_return_if_fail (object != NULL); 01006 object->dont_redraw = FALSE; 01007 } 01008 01009 01030 static void o_grips_end_arc(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01031 int whichone) 01032 { 01033 TOPLEVEL *toplevel = w_current->toplevel; 01034 int arg1, arg2; 01035 01036 /* erase the temporary arc */ 01037 /* o_arc_invalidate_rubber (w_current); */ 01038 01039 /* determination of the parameters to give to o_arc_modify() */ 01040 switch(whichone) { 01041 case ARC_RADIUS: 01042 /* get the radius from w_current */ 01043 arg1 = w_current->distance; 01044 /* second parameter is not used */ 01045 arg2 = -1; 01046 break; 01047 01048 case ARC_START_ANGLE: 01049 /* get the start angle from w_current */ 01050 arg1 = w_current->second_wx; 01051 /* second parameter is not used */ 01052 arg2 = -1; 01053 break; 01054 01055 case ARC_END_ANGLE: 01056 /* get the end angle from w_current */ 01057 arg1 = w_current->second_wy; 01058 /* second parameter is not used */ 01059 arg2 = -1; 01060 break; 01061 01062 default: 01063 return; 01064 } 01065 01066 /* modify the arc with the parameters determined above */ 01067 o_arc_modify(toplevel, o_current, arg1, arg2, whichone); 01068 } 01069 01078 static void o_grips_end_box(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01079 int whichone) 01080 { 01081 TOPLEVEL *toplevel = w_current->toplevel; 01082 int box_width, box_height; 01083 01084 box_width = GET_BOX_WIDTH (w_current); 01085 box_height = GET_BOX_HEIGHT(w_current); 01086 01087 /* don't allow zero width/height boxes 01088 * this ends the box drawing behavior 01089 * we want this? hack */ 01090 if ((box_width == 0) || (box_height == 0)) { 01091 o_box_invalidate_rubber (w_current); 01092 o_invalidate (w_current, o_current); 01093 return; 01094 } 01095 01096 o_box_modify(toplevel, o_current, w_current->second_wx, w_current->second_wy, whichone); 01097 } 01098 01107 static void o_grips_end_path(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01108 int whichone) 01109 { 01110 o_path_modify (w_current->toplevel, o_current, 01111 w_current->second_wx, w_current->second_wy, whichone); 01112 } 01113 01122 static void o_grips_end_picture(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01123 int whichone) 01124 { 01125 TOPLEVEL *toplevel = w_current->toplevel; 01126 01127 /* don't allow zero width/height picturees 01128 * this ends the picture drawing behavior 01129 * we want this? hack */ 01130 if ((GET_PICTURE_WIDTH(w_current) == 0) || (GET_PICTURE_HEIGHT(w_current) == 0)) { 01131 o_picture_invalidate_rubber (w_current); 01132 o_invalidate (w_current, o_current); 01133 return; 01134 } 01135 01136 o_picture_modify(toplevel, o_current, 01137 w_current->second_wx, w_current->second_wy, whichone); 01138 01139 g_object_unref (w_current->current_pixbuf); 01140 w_current->current_pixbuf = NULL; 01141 g_free (w_current->pixbuf_filename); 01142 w_current->pixbuf_filename = NULL; 01143 w_current->pixbuf_wh_ratio = 0; 01144 } 01145 01161 static void o_grips_end_circle(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01162 int whichone) 01163 { 01164 TOPLEVEL *toplevel = w_current->toplevel; 01165 01166 /* don't allow zero radius circles 01167 * this ends the circle drawing behavior 01168 * we want this? hack */ 01169 if (w_current->distance == 0) { 01170 o_circle_invalidate_rubber (w_current); 01171 o_invalidate (w_current, o_current); 01172 return; 01173 } 01174 01175 /* modify the radius of the circle */ 01176 o_circle_modify(toplevel, o_current, w_current->distance, -1, CIRCLE_RADIUS); 01177 } 01178 01195 static void o_grips_end_line(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01196 int whichone) 01197 { 01198 TOPLEVEL *toplevel = w_current->toplevel; 01199 01200 /* don't allow zero length nets / lines / pins 01201 * this ends the net drawing behavior 01202 * we want this? hack */ 01203 if ((w_current->first_wx == w_current->second_wx) && 01204 (w_current->first_wy == w_current->second_wy)) { 01205 o_box_invalidate_rubber (w_current); 01206 o_invalidate (w_current, o_current); 01207 return; 01208 } 01209 01210 /* modify the right line end according to whichone */ 01211 o_line_modify(toplevel, o_current, 01212 w_current->second_wx, w_current->second_wy, whichone); 01213 } 01214 01215 01232 static void o_grips_end_net(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01233 int whichone) 01234 { 01235 TOPLEVEL *toplevel = w_current->toplevel; 01236 GList *connected_objects; 01237 01238 /* don't allow zero length net 01239 * this ends the net drawing behavior 01240 * we want this? hack */ 01241 if ((w_current->first_wx == w_current->second_wx) && 01242 (w_current->first_wy == w_current->second_wy)) { 01243 o_invalidate (w_current, o_current); 01244 return; 01245 } 01246 01247 s_conn_remove_object (toplevel, o_current); 01248 o_net_modify (toplevel, o_current, w_current->second_wx, 01249 w_current->second_wy, w_current->which_grip); 01250 s_conn_update_object (toplevel, o_current); 01251 01252 /* add bus rippers if necessary */ 01253 connected_objects = s_conn_return_others (NULL, o_current); 01254 o_net_add_busrippers (w_current, o_current, connected_objects); 01255 g_list_free (connected_objects); 01256 } 01257 01274 static void o_grips_end_pin(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01275 int whichone) 01276 { 01277 TOPLEVEL *toplevel = w_current->toplevel; 01278 01279 /* don't allow zero length pin 01280 * this ends the pin changing behavior 01281 * we want this? hack */ 01282 if ((w_current->first_wx == w_current->second_wx) && 01283 (w_current->first_wy == w_current->second_wy)) { 01284 o_invalidate (w_current, o_current); 01285 return; 01286 } 01287 01288 s_conn_remove_object (toplevel, o_current); 01289 o_pin_modify (toplevel, o_current, w_current->second_wx, 01290 w_current->second_wy, w_current->which_grip); 01291 s_conn_update_object (toplevel, o_current); 01292 } 01293 01310 static void o_grips_end_bus(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current, 01311 int whichone) 01312 { 01313 TOPLEVEL *toplevel = w_current->toplevel; 01314 01315 /* don't allow zero length bus 01316 * this ends the bus changing behavior 01317 * we want this? hack */ 01318 if ((w_current->first_wx == w_current->second_wx) && 01319 (w_current->first_wy == w_current->second_wy)) { 01320 o_invalidate (w_current, o_current); 01321 return; 01322 } 01323 01324 s_conn_remove_object (toplevel, o_current); 01325 o_bus_modify (toplevel, o_current, w_current->second_wx, 01326 w_current->second_wy, w_current->which_grip); 01327 s_conn_update_object (toplevel, o_current); 01328 } 01329 01330 01347 void o_grips_end(GSCHEM_TOPLEVEL *w_current) 01348 { 01349 TOPLEVEL *toplevel = w_current->toplevel; 01350 OBJECT *object; 01351 int grip; 01352 01353 object = w_current->which_object; 01354 grip = w_current->which_grip; 01355 01356 if (!object) { 01357 /* actually this is an error condition hack */ 01358 w_current->inside_action = 0; 01359 i_set_state(w_current, SELECT); 01360 return; 01361 } 01362 01363 switch(object->type) { 01364 01365 case(OBJ_ARC): 01366 /* modify an arc object */ 01367 o_grips_end_arc(w_current, object, grip); 01368 break; 01369 01370 case(OBJ_BOX): 01371 /* modify a box object */ 01372 o_grips_end_box(w_current, object, grip); 01373 break; 01374 01375 case(OBJ_PATH): 01376 /* modify a path object */ 01377 o_grips_end_path(w_current, object, grip); 01378 break; 01379 01380 case(OBJ_PICTURE): 01381 /* modify a picture object */ 01382 o_grips_end_picture(w_current, object, grip); 01383 break; 01384 01385 case(OBJ_CIRCLE): 01386 /* modify a circle object */ 01387 o_grips_end_circle(w_current, object, grip); 01388 break; 01389 01390 case(OBJ_LINE): 01391 /* modify a line object */ 01392 o_grips_end_line(w_current, object, grip); 01393 break; 01394 01395 case(OBJ_NET): 01396 /* modify a net object */ 01397 o_grips_end_net(w_current, object, grip); 01398 break; 01399 01400 case(OBJ_PIN): 01401 /* modify a pin object */ 01402 o_grips_end_pin(w_current, object, grip); 01403 break; 01404 01405 case(OBJ_BUS): 01406 /* modify a bus object */ 01407 o_grips_end_bus(w_current, object, grip); 01408 break; 01409 01410 default: 01411 return; 01412 } 01413 01414 /* Switch drawing of the object back on */ 01415 object->dont_redraw = FALSE; 01416 o_invalidate (w_current, object); 01417 01418 /* reset global variables */ 01419 w_current->which_grip = -1; 01420 w_current->which_object = NULL; 01421 01422 w_current->rubber_visible = 0; 01423 01424 toplevel->page_current->CHANGED=1; 01425 o_undo_savestate(w_current, UNDO_ALL); 01426 } 01427 01428 01441 int o_grips_size(GSCHEM_TOPLEVEL *w_current) 01442 { 01443 TOPLEVEL *toplevel = w_current->toplevel; 01444 int factor, size; 01445 01446 factor = (int) toplevel->page_current->to_world_x_constant; 01447 if (factor > SMALL_ZOOMFACTOR1) { 01448 /* big zoom factor : small size converted to screen unit */ 01449 size = SCREENabs (w_current, GRIP_SIZE1); 01450 } else if (factor > SMALL_ZOOMFACTOR2) { 01451 /* medium zoom factor : medium size converted to screen unit */ 01452 size = SCREENabs (w_current, GRIP_SIZE2); 01453 } else { 01454 /* small zoom factor : big size converted to screen unit */ 01455 size = SCREENabs (w_current, GRIP_SIZE3); 01456 } 01457 01458 return min(size, MAXIMUM_GRIP_PIXELS/2); 01459 } 01460 01475 void o_grips_draw(GSCHEM_TOPLEVEL *w_current, int wx, int wy) 01476 { 01477 TOPLEVEL *toplevel = w_current->toplevel; 01478 int color; 01479 int size, w_size; 01480 01481 /* 01482 * Depending on the current zoom level, the size of the grip is 01483 * determined. <B>size</B> is half the width and height of the grip. 01484 */ 01485 /* size is half the width of grip */ 01486 size = o_grips_size (w_current); 01487 w_size = WORLDabs (w_current, size); 01488 01489 /* 01490 * The grip can be displayed or erased : if <B>toplevel->override_color</B> 01491 * is not set the grip is drawn with the selection color ; if 01492 * <B>toplevel->override_color</B> is set then the color it refers it 01493 * is used. This way the grip can be erased if this color is the 01494 * background color. 01495 */ 01496 if (toplevel->override_color != -1 ) { 01497 /* override : use the override_color instead */ 01498 color = toplevel->override_color; 01499 } else { 01500 /* use the normal selection color */ 01501 color = SELECT_COLOR; 01502 } 01503 01504 /* You can only tell an offset of the grip when it is very small, 01505 * at which point, the object it's on is probably drawn 1px wide. 01506 * Pass 0 as a hint that we're centering on a "hardware" line. 01507 */ 01508 gschem_cairo_center_box (w_current, 0, 0, wx, wy, w_size, w_size); 01509 01510 gschem_cairo_set_source_color (w_current, x_color_lookup (color)); 01511 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); 01512 } 01513 01514 01522 void o_grips_draw_rubber (GSCHEM_TOPLEVEL *w_current) 01523 { 01524 g_return_if_fail (w_current->which_object != NULL); 01525 01526 switch(w_current->which_object->type) { 01527 case OBJ_ARC: 01528 o_arc_draw_rubber (w_current); 01529 break; 01530 01531 case OBJ_BOX: 01532 o_box_draw_rubber (w_current); 01533 break; 01534 01535 case OBJ_PATH: 01536 o_path_draw_rubber (w_current); 01537 break; 01538 01539 case OBJ_PICTURE: 01540 o_picture_draw_rubber (w_current); 01541 break; 01542 01543 case OBJ_CIRCLE: 01544 o_circle_draw_rubber (w_current); 01545 break; 01546 01547 case OBJ_LINE: 01548 case OBJ_NET: 01549 case OBJ_PIN: 01550 case OBJ_BUS: 01551 o_line_draw_rubber (w_current); 01552 break; 01553 01554 default: 01555 return; /* error condition */ 01556 } 01557 }