gschem

o_cue.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 <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 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines