gschem

o_basic.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 #include <stdio.h>
00022 
00023 #include "gschem.h"
00024 
00025 #ifdef HAVE_LIBDMALLOC
00026 #include <dmalloc.h>
00027 #endif
00028 
00029 #define INVALIDATE_MARGIN 1
00030 
00040 void o_redraw_rects (GSCHEM_TOPLEVEL *w_current,
00041                      GdkRectangle *rectangles, int n_rectangles)
00042 {
00043   TOPLEVEL *toplevel = w_current->toplevel;
00044   gboolean draw_selected;
00045   int grip_half_size;
00046   int cue_half_size;
00047   int bloat;
00048   int i;
00049   GList *obj_list;
00050   GList *iter;
00051   BOX *world_rects;
00052 
00053   for (i = 0; i < n_rectangles; i++) {
00054     x_repaint_background_region (w_current, rectangles[i].x, rectangles[i].y,
00055                                  rectangles[i].width, rectangles[i].height);
00056   }
00057 
00058   g_return_if_fail (toplevel != NULL);
00059   g_return_if_fail (toplevel->page_current != NULL);
00060 
00061   grip_half_size = o_grips_size (w_current);
00062   cue_half_size = SCREENabs (w_current, CUE_BOX_SIZE);
00063   bloat = MAX (grip_half_size, cue_half_size);
00064 
00065   world_rects = g_new (BOX, n_rectangles);
00066 
00067   for (i = 0; i < n_rectangles; i++) {
00068     int x, y, width, height;
00069 
00070     x = rectangles[i].x;
00071     y = rectangles[i].y;
00072     width = rectangles[i].width;
00073     height = rectangles[i].height;
00074 
00075     SCREENtoWORLD (w_current, x - bloat, y + height + bloat,
00076                    &world_rects[i].lower_x, &world_rects[i].lower_y);
00077     SCREENtoWORLD (w_current, x + width + bloat, y - bloat,
00078                    &world_rects[i].upper_x, &world_rects[i].upper_y);
00079   }
00080 
00081   obj_list = s_page_objects_in_regions (toplevel, toplevel->page_current,
00082                                         world_rects, n_rectangles);
00083   g_free (world_rects);
00084 
00085   draw_selected = !(w_current->inside_action &&
00086                     ((w_current->event_state == MOVE) ||
00087                      (w_current->event_state == ENDMOVE)));
00088 
00089   for (iter = obj_list; iter != NULL; iter = g_list_next (iter)) {
00090     OBJECT *o_current = iter->data;
00091 
00092     if (o_current->dont_redraw ||
00093         (!draw_selected && o_current->selected))
00094       continue;
00095 
00096     o_redraw_single (w_current, o_current);
00097   }
00098 
00099   o_cue_redraw_all (w_current, obj_list, draw_selected);
00100 
00101   if (w_current->inside_action) {
00102     /* Redraw the rubberband objects (if they were previously visible) */
00103     switch (w_current->event_state) {
00104       case MOVE:
00105       case ENDMOVE:
00106         if (w_current->last_drawb_mode != -1) {
00107           o_move_draw_rubber (w_current, TRUE);
00108         }
00109         break;
00110 
00111       case ENDCOPY:
00112       case ENDMCOPY:
00113       case ENDCOMP:
00114       case ENDTEXT:
00115       case ENDPASTE:
00116         if (w_current->rubber_visible)
00117           o_place_draw_rubber (w_current, TRUE);
00118         break;
00119 
00120       case STARTDRAWNET:
00121       case DRAWNET:
00122       case NETCONT:
00123         if (w_current->rubber_visible)
00124           o_net_draw_rubber (w_current);
00125         break;
00126 
00127       case STARTDRAWBUS:
00128       case DRAWBUS:
00129       case BUSCONT:
00130         if (w_current->rubber_visible)
00131           o_bus_draw_rubber(w_current);
00132         break;
00133 
00134       case GRIPS:
00135         if (w_current->rubber_visible)
00136           o_grips_draw_rubber (w_current);
00137         break;
00138 
00139       case SBOX:
00140         if (w_current->rubber_visible)
00141           o_select_box_draw_rubber (w_current);
00142         break;
00143 
00144       case ZOOMBOXEND:
00145         if (w_current->rubber_visible)
00146           a_zoom_box_draw_rubber (w_current);
00147         break;
00148 
00149       case ENDLINE:
00150         if (w_current->rubber_visible)
00151           o_line_draw_rubber (w_current);
00152         break;
00153 
00154       case ENDBOX:
00155         if (w_current->rubber_visible)
00156           o_box_draw_rubber (w_current);
00157         break;
00158 
00159       case ENDPICTURE:
00160         if (w_current->rubber_visible)
00161           o_picture_draw_rubber (w_current);
00162         break;
00163 
00164       case ENDCIRCLE:
00165         if (w_current->rubber_visible)
00166           o_circle_draw_rubber (w_current);
00167         break;
00168 
00169       case ENDARC:
00170         if (w_current->rubber_visible)
00171           o_arc_draw_rubber (w_current);
00172         break;
00173 
00174       case ENDPIN:
00175         if (w_current->rubber_visible)
00176           o_pin_draw_rubber (w_current);
00177         break;
00178     }
00179   }
00180 
00181   g_list_free (obj_list);
00182 }
00183 
00184 
00190 void o_redraw (GSCHEM_TOPLEVEL *w_current, GList *object_list, gboolean draw_selected)
00191 {
00192   OBJECT *o_current;
00193   GList *iter;
00194 
00195   for (iter = object_list; iter != NULL; iter = g_list_next (iter)) {
00196     o_current = (OBJECT *)iter->data;
00197 
00198     if (o_current->dont_redraw ||
00199         (!draw_selected && o_current->selected))
00200       continue;
00201 
00202     o_redraw_single (w_current, o_current);
00203   }
00204 }
00205 
00214 void o_redraw_single(GSCHEM_TOPLEVEL *w_current, OBJECT *o_current)
00215 {
00216   void (*func) (GSCHEM_TOPLEVEL *, OBJECT *) = NULL;
00217 
00218   if (o_current == NULL)
00219     return;
00220 
00221   switch (o_current->type) {
00222       case OBJ_LINE:    func = o_line_draw;    break;
00223       case OBJ_NET:     func = o_net_draw;     break;
00224       case OBJ_BUS:     func = o_bus_draw;     break;
00225       case OBJ_BOX:     func = o_box_draw;     break;
00226       case OBJ_PICTURE: func = o_picture_draw; break;
00227       case OBJ_CIRCLE:  func = o_circle_draw;  break;
00228       case OBJ_PLACEHOLDER:
00229       case OBJ_COMPLEX: func = o_complex_draw; break;
00230       case OBJ_TEXT:    func = o_text_draw;    break;
00231       case OBJ_PATH:    func = o_path_draw;    break;
00232       case OBJ_PIN:     func = o_pin_draw;     break;
00233       case OBJ_ARC:     func = o_arc_draw;     break;
00234       default:
00235         g_critical ("o_redraw_single: object %p has bad type '%c'\n",
00236                     o_current, o_current->type);
00237   }
00238 
00239   if (func != NULL)
00240     (*func) (w_current, o_current);
00241 }
00242 
00243 
00249 int o_invalidate_rubber (GSCHEM_TOPLEVEL *w_current)
00250 {
00251   /* return FALSE if it did not erase anything */
00252 
00253   if (!w_current->inside_action)
00254     return(FALSE);
00255 
00256   switch(w_current->event_state) {
00257 
00258     case(STARTDRAWBUS):
00259     case(DRAWBUS):
00260     case(BUSCONT):
00261       o_bus_invalidate_rubber (w_current);
00262     break;
00263 
00264     case(STARTDRAWNET):
00265     case(DRAWNET):
00266     case(NETCONT):
00267       o_net_invalidate_rubber (w_current);
00268     break;
00269 
00270     case(DRAWPIN):
00271     case(ENDPIN):
00272       o_pin_invalidate_rubber (w_current);
00273     break;
00274 
00275     case(DRAWLINE):
00276     case(ENDLINE):
00277       o_line_invalidate_rubber (w_current);
00278     break;
00279 
00280     case(DRAWBOX):
00281     case(ENDBOX):
00282       o_box_invalidate_rubber (w_current);
00283     break;
00284 
00285     case(DRAWPICTURE):
00286     case(ENDPICTURE):
00287       o_picture_invalidate_rubber (w_current);
00288     break;
00289 
00290     case(DRAWCIRCLE):
00291     case(ENDCIRCLE):
00292       o_circle_invalidate_rubber (w_current);
00293     break;
00294 
00295     case(DRAWARC):
00296     case(ENDARC):
00297       o_arc_invalidate_rubber (w_current);
00298     break;
00299 
00300     default:
00301       return(FALSE);
00302     break;
00303   }
00304 
00305   return(TRUE);
00306 }
00307 
00308 
00319 int o_redraw_cleanstates(GSCHEM_TOPLEVEL *w_current)
00320 {
00321   TOPLEVEL *toplevel = w_current->toplevel;
00322   /* returns FALSE if the function was'nt nessecary */
00323   if (w_current->inside_action == 0) {
00324     return FALSE;
00325   }
00326 
00327   switch (w_current->event_state) {
00328     /* all states with something on the dc */
00329     case(ENDCOMP):
00330       /* De-select the lists in the component selector */
00331       x_compselect_deselect (w_current);
00332 
00333       /* Fall through */
00334     case(COPY):
00335     case(MCOPY):
00336     case(DRAWBUS):
00337     case(DRAWNET):
00338     case(ENDARC):
00339     case(ENDBOX):
00340     case(ENDCIRCLE):
00341     case(ENDCOPY):
00342     case(ENDMCOPY):
00343     case(ENDLINE):
00344     case(ENDMOVE):
00345     case(ENDPASTE):
00346     case(ENDPIN):
00347     case(ENDTEXT):
00348     case(GRIPS):
00349     case(MOVE):
00350     case(NETCONT):
00351     case(ZOOMBOXEND):
00352       /* it is possible to cancel in the middle of a place,
00353        * so lets be sure to clean up the place_list structure */
00354 
00355       /* If we're cancelling from a move action, re-wind the
00356        * page contents back to their state before we started. */
00357       if ((w_current->event_state == MOVE) ||
00358           (w_current->event_state == ENDMOVE)) {
00359         o_move_cancel (w_current);
00360       }
00361 
00362       /* If we're cancelling from a grip action, call the specific cancel
00363        * routine to reset the visibility of the object being modified */
00364       if (w_current->event_state == GRIPS)
00365         o_grips_cancel (w_current);
00366 
00367       /* Free the place list and its contents. If we were in a move
00368        * action, the list (refering to objects on the page) would
00369        * already have been cleared in o_move_cancel(), so this is OK. */
00370       s_delete_object_glist(toplevel, toplevel->page_current->place_list);
00371       toplevel->page_current->place_list = NULL;
00372 
00373       w_current->inside_action = 0;
00374 
00375       /* touch the select state */
00376       i_set_state(w_current, SELECT);
00377 
00378       /* from i_callback_cancel() */
00379       o_invalidate_all (w_current);
00380       return TRUE;
00381 
00382     /* all remaining states without dc changes */
00383     case(NONE):
00384     case(SELECT):
00385     case(DRAWLINE):
00386     case(DRAWBOX):
00387     case(DRAWCIRCLE):
00388     case(ZOOM):
00389     case(PAN):
00390     case(BUSCONT):
00391     case(DRAWARC):
00392     case(DRAWPICTURE):
00393     case(DRAWPIN):
00394     case(ENDMIRROR):
00395     case(ENDPICTURE):
00396     case(ENDROTATEP):
00397     case(ENDROUTENET):
00398     case(MOUSEPAN):
00399     case(SBOX):
00400     case(STARTCOPY):
00401     case(STARTMCOPY):
00402     case(STARTDRAWBUS):
00403     case(STARTDRAWNET):
00404     case(STARTMOVE):
00405     case(STARTPAN):
00406     case(STARTPASTE):
00407     case(STARTROUTENET):
00408     case(STARTSELECT):
00409     case(ZOOMBOXSTART):
00410       return FALSE;
00411   }
00412 
00413   return FALSE;
00414 }
00415 
00416 
00422 void o_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
00423 {
00424   void (*func) (GSCHEM_TOPLEVEL *, int, int, OBJECT*) = NULL;
00425 
00426   switch (object->type) {
00427       case OBJ_LINE:    func = o_line_draw_place;       break;
00428       case OBJ_NET:     func = o_net_draw_place;        break;
00429       case OBJ_BUS:     func = o_bus_draw_place;        break;
00430       case OBJ_BOX:     func = o_box_draw_place;        break;
00431       case OBJ_PICTURE: func = o_picture_draw_place;    break;
00432       case OBJ_CIRCLE:  func = o_circle_draw_place;     break;
00433       case OBJ_PLACEHOLDER:
00434       case OBJ_COMPLEX: func = o_complex_draw_place;    break;
00435       case OBJ_TEXT:    func = o_text_draw_place;       break;
00436       case OBJ_PATH:    func = o_path_draw_place;       break;
00437       case OBJ_PIN:     func = o_pin_draw_place;        break;
00438       case OBJ_ARC:     func = o_arc_draw_place;        break;
00439       default:
00440         g_assert_not_reached ();
00441   }
00442 
00443   if (func != NULL) {
00444     (*func) (w_current, dx, dy, object);
00445   }
00446 }
00447 
00448 
00454 void o_glist_draw_place (GSCHEM_TOPLEVEL *w_current, int dx, int dy, GList *list)
00455 {
00456   GList *iter = list;
00457 
00458   while (iter != NULL) {
00459     o_draw_place (w_current, dx, dy, (OBJECT *)iter->data);
00460     iter = g_list_next(iter);
00461   }
00462 }
00463 
00464 
00494 void o_invalidate_rect (GSCHEM_TOPLEVEL *w_current,
00495                         int x1, int y1, int x2, int y2)
00496 {
00497   GdkRectangle rect;
00498   int grip_half_size;
00499   int cue_half_size;
00500   int bloat;
00501 
00502   /* BUG: We get called when rendering an image, and w_current->window
00503    *      is a GdkPixmap. Ensure we only invalidate GdkWindows. */
00504   if (!GDK_IS_WINDOW( w_current->window ))
00505     return;
00506 
00507   grip_half_size = o_grips_size (w_current);
00508   cue_half_size = SCREENabs (w_current, CUE_BOX_SIZE);
00509   bloat = MAX (grip_half_size, cue_half_size) + INVALIDATE_MARGIN;
00510 
00511   rect.x = MIN(x1, x2) - bloat;
00512   rect.y = MIN(y1, y2) - bloat;
00513   rect.width = 1 + abs( x1 - x2 ) + 2 * bloat;
00514   rect.height = 1 + abs( y1 - y2 ) + 2 * bloat;
00515   gdk_window_invalidate_rect( w_current->window, &rect, FALSE );
00516 }
00517 
00518 
00527 void o_invalidate_all (GSCHEM_TOPLEVEL *w_current)
00528 {
00529   gdk_window_invalidate_rect (w_current->window, NULL, FALSE);
00530 }
00531 
00532 
00542 void o_invalidate (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
00543 {
00544   TOPLEVEL *toplevel = w_current->toplevel;
00545   int left, top, bottom, right;
00546   int s_left, s_top, s_bottom, s_right;
00547   if (world_get_single_object_bounds(toplevel, object, &left,  &top,
00548                                                        &right, &bottom)) {
00549     WORLDtoSCREEN (w_current, left, top, &s_left, &s_top);
00550     WORLDtoSCREEN (w_current, right, bottom, &s_right, &s_bottom);
00551     o_invalidate_rect (w_current, s_left, s_top, s_right, s_bottom);
00552   }
00553 }
00554 
00555 
00565 void o_invalidate_glist (GSCHEM_TOPLEVEL *w_current, GList *list)
00566 {
00567   TOPLEVEL *toplevel = w_current->toplevel;
00568   int left, top, bottom, right;
00569   int s_left, s_top, s_bottom, s_right;
00570   if (world_get_object_glist_bounds (toplevel, list, &left,  &top,
00571                                                      &right, &bottom)) {
00572     WORLDtoSCREEN (w_current, left, top, &s_left, &s_top);
00573     WORLDtoSCREEN (w_current, right, bottom, &s_right, &s_bottom);
00574     o_invalidate_rect (w_current, s_left, s_top, s_right, s_bottom);
00575   }
00576 }
00577 
00578 
00597 COLOR *o_drawing_color (GSCHEM_TOPLEVEL *w_current, OBJECT *object)
00598 {
00599   int color_idx;
00600   OBJECT *temp;
00601 
00602   color_idx = object->color;
00603 
00604   if (object->selected)
00605     color_idx = SELECT_COLOR;
00606 
00607   /* Check if the object, or its parent(s) are selected */
00608   for (temp = object; temp != NULL; temp = temp->parent) {
00609     if (temp->selected) {
00610       color_idx = SELECT_COLOR;
00611       break;
00612     }
00613   }
00614 
00615   if (w_current->toplevel->override_color != -1)
00616     color_idx = w_current->toplevel->override_color;
00617 
00618   return x_color_lookup (color_idx);
00619 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines