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 <string.h> 00024 #include <math.h> /* For M_PI */ 00025 00026 #include "gschem.h" 00027 00028 #ifdef HAVE_LIBDMALLOC 00029 #include <dmalloc.h> 00030 #endif 00031 00037 void o_cue_redraw_all (GSCHEM_TOPLEVEL *w_current, GList *list, gboolean draw_selected) 00038 { 00039 OBJECT *o_current; 00040 GList *iter; 00041 00042 iter = list; 00043 while (iter != NULL) { 00044 o_current = (OBJECT *)iter->data; 00045 switch(o_current->type) { 00046 case(OBJ_NET): 00047 case(OBJ_BUS): 00048 case(OBJ_PIN): 00049 if (!(o_current->dont_redraw || 00050 (o_current->selected && !draw_selected))) { 00051 o_cue_draw_single(w_current, o_current); 00052 if (o_current->selected && w_current->draw_grips) { 00053 o_line_draw_grips (w_current, o_current); 00054 } 00055 } 00056 break; 00057 00058 case(OBJ_COMPLEX): 00059 case(OBJ_PLACEHOLDER): 00060 if (!(o_current->dont_redraw || 00061 (o_current->selected && !draw_selected))) { 00062 o_cue_redraw_all(w_current, o_current->complex->prim_objs, 00063 draw_selected); 00064 } 00065 break; 00066 } 00067 00068 iter = g_list_next (iter); 00069 } 00070 } 00071 00072 00076 static void o_cue_set_color(GSCHEM_TOPLEVEL *w_current, int color) 00077 { 00078 if (w_current->toplevel->override_color != -1 ) { 00079 gschem_cairo_set_source_color (w_current, x_color_lookup (w_current->toplevel->override_color)); 00080 } else { 00081 gschem_cairo_set_source_color (w_current, x_color_lookup (color)); 00082 } 00083 } 00084 00085 00101 static void draw_junction_cue (GSCHEM_TOPLEVEL *w_current, 00102 int x, int y, int bus_involved) 00103 { 00104 int size; 00105 int line_width; 00106 00107 if (bus_involved) { 00108 size = JUNCTION_CUE_SIZE_BUS / 2; 00109 line_width = BUS_WIDTH; 00110 } else { 00111 size = JUNCTION_CUE_SIZE_NET / 2; 00112 line_width = NET_WIDTH; 00113 } 00114 00115 gschem_cairo_center_arc (w_current, line_width, -1, x, y, size, 0, 360); 00116 o_cue_set_color (w_current, JUNCTION_COLOR); 00117 cairo_fill (w_current->cr); 00118 } 00119 00120 00126 void o_cue_draw_lowlevel(GSCHEM_TOPLEVEL *w_current, OBJECT *object, int whichone) 00127 { 00128 int x, y; 00129 GList *cl_current; 00130 CONN *conn; 00131 int type, count = 0; 00132 int done = FALSE; 00133 int size; 00134 int bus_involved = FALSE; 00135 00136 g_return_if_fail (whichone == 0 || whichone == 1); 00137 00138 x = object->line->x[whichone]; 00139 y = object->line->y[whichone]; 00140 00141 type = CONN_ENDPOINT; 00142 00143 if (object->type == OBJ_BUS || 00144 (object->type == OBJ_PIN && object->pin_type == PIN_TYPE_BUS)) 00145 bus_involved = TRUE; 00146 00147 cl_current = object->conn_list; 00148 while (cl_current != NULL && !done) { 00149 conn = (CONN *) cl_current->data; 00150 00151 if (conn->x == x && conn->y == y) { 00152 00153 if (conn->other_object && 00154 (conn->other_object->type == OBJ_BUS || 00155 (conn->other_object->type == OBJ_PIN && 00156 conn->other_object->pin_type == PIN_TYPE_BUS))) 00157 bus_involved=TRUE; 00158 00159 switch(conn->type) { 00160 00161 case(CONN_ENDPOINT): 00162 count++; 00163 break; 00164 00165 case(CONN_MIDPOINT): 00166 type = CONN_MIDPOINT; 00167 done = TRUE; 00168 count = 0; 00169 break; 00170 } 00171 } 00172 00173 cl_current = g_list_next(cl_current); 00174 } 00175 00176 #if DEBUG 00177 printf("type: %d count: %d\n", type, count); 00178 #endif 00179 00180 switch(type) { 00181 00182 case(CONN_ENDPOINT): 00183 if (object->type == OBJ_NET || object->type == OBJ_PIN) { 00184 if (count < 1) { /* Didn't find anything connected directly there */ 00185 if ((object->type == OBJ_NET) 00186 && o_net_is_fully_connected (w_current->toplevel, object)) { 00187 /* Probably connected, so draw friendly arrow */ 00188 /* Here we compute a transformation so that the arrow is 00189 aligned with the net segment. 00190 00191 FIXME This probably isn't efficient, unfortunately. */ 00192 cairo_save (w_current->cr); 00193 00194 int s_x, s_y; 00195 WORLDtoSCREEN (w_current, x, y, &s_x, &s_y); 00196 double s_size = SCREENabs (w_current, CUE_BOX_SIZE); 00197 00198 cairo_matrix_t mtx; 00199 double dx = object->line->x[whichone] - object->line->x[!whichone]; 00200 double dy = object->line->y[whichone] - object->line->y[!whichone]; 00201 double len = hypot (dx, dy); 00202 if (len != 0) { 00203 dx /= len; 00204 dy /= len; 00205 00206 cairo_matrix_init (&mtx, dx, -dy, dy, dx, s_x, s_y); 00207 } else { 00208 cairo_matrix_init_translate (&mtx, s_x, s_y); 00209 } 00210 cairo_transform (w_current->cr, &mtx); 00211 00212 cairo_move_to (w_current->cr, -s_size, -s_size); 00213 cairo_line_to (w_current->cr, -s_size, s_size); 00214 cairo_line_to (w_current->cr, s_size, 0); 00215 cairo_close_path (w_current->cr); 00216 o_cue_set_color (w_current, JUNCTION_COLOR); 00217 cairo_fill (w_current->cr); 00218 00219 cairo_restore (w_current->cr); 00220 } else { 00221 /* Not properly connected, so draw warning box */ 00222 size = CUE_BOX_SIZE; 00223 gschem_cairo_center_box (w_current, -1, -1, x, y, size, size); 00224 o_cue_set_color (w_current, NET_ENDPOINT_COLOR); 00225 cairo_fill (w_current->cr); 00226 } 00227 } else if (count >= 2) { 00228 draw_junction_cue (w_current, x, y, bus_involved); 00229 } 00230 } 00231 break; 00232 00233 case(CONN_MIDPOINT): 00234 draw_junction_cue (w_current, x, y, bus_involved); 00235 break; 00236 00237 /* here is where you draw bus rippers */ 00238 00239 } 00240 00241 } 00242 00243 00249 void o_cue_draw_lowlevel_midpoints(GSCHEM_TOPLEVEL *w_current, OBJECT *object) 00250 { 00251 GList *iter; 00252 int bus_involved; 00253 00254 for (iter = object->conn_list; iter != NULL; iter = g_list_next (iter)) { 00255 CONN *conn = iter->data; 00256 00257 if (conn->type == CONN_MIDPOINT) { 00258 bus_involved = (object->type == OBJ_BUS || 00259 (conn->other_object && 00260 conn->other_object->type == OBJ_BUS)); 00261 draw_junction_cue (w_current, conn->x, conn->y, bus_involved); 00262 } 00263 } 00264 } 00265 00266 00272 void o_cue_draw_single(GSCHEM_TOPLEVEL *w_current, OBJECT *object) 00273 { 00274 if (!object) { 00275 return; 00276 } 00277 00278 if (object->type != OBJ_NET && object->type != OBJ_PIN && 00279 object->type != OBJ_BUS) { 00280 return; 00281 } 00282 00283 if (object->type != OBJ_PIN) { 00284 o_cue_draw_lowlevel(w_current, object, 0); 00285 o_cue_draw_lowlevel(w_current, object, 1); 00286 o_cue_draw_lowlevel_midpoints(w_current, object); 00287 } else { 00288 o_cue_draw_lowlevel(w_current, object, object->whichend); 00289 } 00290 } 00291 00292 00298 void o_cue_draw_list(GSCHEM_TOPLEVEL *w_current, GList *object_list) 00299 { 00300 OBJECT *object; 00301 GList *ol_current; 00302 00303 ol_current = object_list; 00304 while(ol_current != NULL) { 00305 object = (OBJECT *) ol_current->data; 00306 00307 o_cue_draw_single(w_current, object); 00308 00309 ol_current = g_list_next(ol_current); 00310 } 00311 }