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 #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 }