gschem

o_grips.c

Go to the documentation of this file.
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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines