gschem
|
00001 /* gEDA - GPL Electronic Design Automation 00002 * gschem - gEDA Schematic Capture 00003 * Copyright (C) 1998-2010 Ales Hvezda 00004 * Copyright (C) 1998-2011 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 #include <stdio.h> 00022 #include <math.h> 00023 00024 #include "gschem.h" 00025 00026 #ifdef HAVE_LIBDMALLOC 00027 #include <dmalloc.h> 00028 #endif 00029 00030 00044 void o_arc_draw(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) 00045 { 00046 if (o_current->arc == NULL) { 00047 return; 00048 } 00049 00050 gschem_cairo_arc (w_current, o_current->line_width, 00051 o_current->arc->x, 00052 o_current->arc->y, 00053 o_current->arc->width / 2, 00054 o_current->arc->start_angle, 00055 o_current->arc->end_angle); 00056 00057 gschem_cairo_set_source_color (w_current, 00058 o_drawing_color (w_current, o_current)); 00059 gschem_cairo_stroke (w_current, o_current->line_type, 00060 o_current->line_end, 00061 o_current->line_width, 00062 o_current->line_length, 00063 o_current->line_space); 00064 00065 if (o_current->selected && w_current->draw_grips == TRUE) { 00066 o_arc_draw_grips (w_current, o_current); 00067 } 00068 } 00069 00075 void o_arc_invalidate_rubber (GSCHEM_TOPLEVEL *w_current) 00076 { 00077 int cx, cy, radius; 00078 00079 WORLDtoSCREEN (w_current, w_current->first_wx, w_current->first_wy, &cx, &cy); 00080 radius = SCREENabs (w_current, w_current->distance); 00081 00082 /* FIXME: This isn't a tight bounding box */ 00083 o_invalidate_rect (w_current, cx - radius, cy - radius, 00084 cx + radius, cy + radius); 00085 } 00086 00100 void o_arc_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *o_current) 00101 { 00102 g_return_if_fail (o_current->arc != NULL); 00103 00104 gschem_cairo_arc (w_current, 0, o_current->arc->x + dx, 00105 o_current->arc->y + dy, 00106 o_current->arc->width / 2, 00107 o_current->arc->start_angle, 00108 o_current->arc->end_angle); 00109 00110 gschem_cairo_set_source_color (w_current, 00111 x_color_lookup_dark (o_current->color)); 00112 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); 00113 } 00114 00129 void o_arc_start(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00130 { 00131 /* set the center of the arc */ 00132 w_current->first_wx = w_x; 00133 w_current->first_wy = w_y; 00134 00135 /* set the radius */ 00136 w_current->distance = 0; 00137 00138 /* set the start and end angles */ 00139 w_current->second_wx = w_current->second_wy = 0; 00140 00141 /* start the rubberbanding process of the radius */ 00142 o_arc_invalidate_rubber (w_current); 00143 w_current->rubber_visible = 1; 00144 } 00145 00163 void o_arc_end1(GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00164 { 00165 g_assert( w_current->inside_action != 0 ); 00166 00167 /* erases the previous temporary radius segment */ 00168 /* o_arc_invalidate_rubber (w_current); */ 00169 w_current->rubber_visible = 0; 00170 00171 /* ack! zero length radius */ 00172 if (w_current->distance == 0) { 00173 return; 00174 } 00175 00176 #if DEBUG 00177 printf("DIST: %d\n", w_current->distance); 00178 #endif 00179 00180 /* open a dialog to input the start and end angle */ 00181 arc_angle_dialog(w_current, NULL); 00182 } 00183 00197 void o_arc_end4(GSCHEM_TOPLEVEL *w_current, int radius, 00198 int start_angle, int end_angle) 00199 { 00200 TOPLEVEL *toplevel = w_current->toplevel; 00201 OBJECT *new_obj; 00202 00203 /* create, initialize and link the new arc object */ 00204 new_obj = o_arc_new (toplevel, OBJ_ARC, GRAPHIC_COLOR, 00205 w_current->first_wx, w_current->first_wy, 00206 radius, start_angle, end_angle); 00207 s_page_append (toplevel, toplevel->page_current, new_obj); 00208 00209 w_current->first_wx = -1; 00210 w_current->first_wy = -1; 00211 w_current->distance = 0; 00212 00213 /* Call add-objects-hook */ 00214 g_run_hook_object (w_current, "%add-objects-hook", new_obj); 00215 00216 toplevel->page_current->CHANGED = 1; 00217 00218 o_undo_savestate(w_current, UNDO_ALL); 00219 } 00220 00258 void o_arc_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, int whichone) 00259 { 00260 int diff_x, diff_y, angle_deg; 00261 00262 /* erase the previous temporary arc */ 00263 if (w_current->rubber_visible) 00264 o_arc_invalidate_rubber (w_current); 00265 00266 if(whichone == ARC_RADIUS) { 00267 /* 00268 * The radius is taken as the biggest distance on the x and y 00269 * axis between the center of the arc and the mouse position. 00270 */ 00271 diff_x = abs(w_current->first_wx - snap_grid (w_current, w_x)); 00272 diff_y = abs(w_current->first_wy - snap_grid (w_current, w_y)); 00273 w_current->distance = max(diff_x, diff_y); 00274 } 00275 else if((whichone == ARC_START_ANGLE) || (whichone == ARC_END_ANGLE)) { 00276 /* compute the angle */ 00277 diff_x = w_x - w_current->first_wx; 00278 diff_y = w_y - w_current->first_wy; 00279 angle_deg = atan2 (diff_y, diff_x) * 180 / M_PI; 00280 00281 /* set the start or end angle with this angle */ 00282 switch(whichone) { 00283 case ARC_START_ANGLE: 00284 w_current->second_wx = (angle_deg + 360) % 360; 00285 break; 00286 00287 case ARC_END_ANGLE: 00288 w_current->second_wy = (((angle_deg + 360) % 360) - 00289 w_current->second_wx + 360) % 360; 00290 if (w_current->which_object->arc->end_angle < 0) 00291 w_current->second_wy = w_current->second_wy - 360; 00292 if (w_current->second_wy == 0) 00293 w_current->second_wy = 360; 00294 break; 00295 00296 // No default required - one of above two branches 00297 // *must* be taken - Coverity ID 201571 00298 } 00299 00300 } 00301 00302 /* draw the new temporary arc */ 00303 o_arc_invalidate_rubber (w_current); 00304 w_current->rubber_visible = 1; 00305 } 00306 00318 void o_arc_draw_rubber (GSCHEM_TOPLEVEL *w_current) 00319 { 00320 double rad_angle; 00321 int rdx, rdy; 00322 00323 gschem_cairo_arc (w_current, 0, w_current->first_wx, 00324 w_current->first_wy, 00325 w_current->distance, 00326 w_current->second_wx, 00327 w_current->second_wy); 00328 00329 gschem_cairo_set_source_color (w_current, 00330 x_color_lookup_dark (SELECT_COLOR)); 00331 00332 /* draw the radius line */ 00333 rad_angle = ((double) w_current->second_wx) * M_PI / 180; 00334 rdx = (double) w_current->distance * cos (rad_angle); 00335 rdy = (double) w_current->distance * sin (rad_angle); 00336 00337 gschem_cairo_line (w_current, END_NONE, 0, w_current->first_wx, 00338 w_current->first_wy, 00339 w_current->first_wx + rdx, 00340 w_current->first_wy + rdy); 00341 00342 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); 00343 } 00344 00353 void o_arc_draw_grips(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current) 00354 { 00355 double radius, start_angle, end_angle; 00356 int x1, y1, x2, y2, x3, y3; 00357 00358 if (w_current->draw_grips == FALSE) 00359 return; 00360 00361 /* 00362 * An arc has three grips: 00363 * <DL> 00364 * <DT>*</DT><DD>one at the center that allows changes on the 00365 * radius - at (<B>x</B>,<B>y</B>). 00366 * <DT>*</DT><DD>one at the start of the arc - at (<B>x1</B>,<B>y1</B>). 00367 * <DT>*</DT><DD>one at the end of the arc - at (<B>x2</B>,<B>y2</B>). 00368 */ 00369 00370 x1 = o_current->arc->x; 00371 y1 = o_current->arc->y; 00372 00373 radius = o_current->arc->width / 2.; 00374 start_angle = o_current->arc->start_angle; 00375 end_angle = o_current->arc->end_angle; 00376 00377 x2 = x1 + radius * cos ( start_angle * M_PI / 180); 00378 y2 = y1 + radius * sin ( start_angle * M_PI / 180); 00379 x3 = x1 + radius * cos ((start_angle + end_angle) * M_PI / 180); 00380 y3 = y1 + radius * sin ((start_angle + end_angle) * M_PI / 180); 00381 00382 /* draw the grip at the center */ 00383 o_grips_draw (w_current, x1, y1); 00384 00385 /* draw the grip at the start_angle end of the arc */ 00386 o_grips_draw (w_current, x2, y2); 00387 00388 /* draw the grip at the end_angle end of the arc */ 00389 o_grips_draw (w_current, x3, y3); 00390 00391 }