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 00023 #include "gschem.h" 00024 00025 #ifdef HAVE_LIBDMALLOC 00026 #include <dmalloc.h> 00027 #endif 00028 00034 void o_place_start (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00035 { 00036 w_current->second_wx = w_x; 00037 w_current->second_wy = w_y; 00038 00039 o_place_invalidate_rubber (w_current, TRUE); 00040 w_current->rubber_visible = 1; 00041 } 00042 00048 void o_place_end (GSCHEM_TOPLEVEL *w_current, 00049 int w_x, int w_y, 00050 int continue_placing, 00051 GList **ret_new_objects, 00052 const char* hook_name) 00053 { 00054 TOPLEVEL *toplevel = w_current->toplevel; 00055 int w_diff_x, w_diff_y; 00056 OBJECT *o_current; 00057 PAGE *p_current; 00058 GList *temp_dest_list = NULL; 00059 GList *connected_objects = NULL; 00060 GList *iter; 00061 00062 /* erase old image */ 00063 /* o_place_invaidate_rubber (w_current, FALSE); */ 00064 w_current->rubber_visible = 0; 00065 00066 /* Calc final object positions */ 00067 w_current->second_wx = w_x; 00068 w_current->second_wy = w_y; 00069 00070 w_diff_x = w_current->second_wx - w_current->first_wx; 00071 w_diff_y = w_current->second_wy - w_current->first_wy; 00072 00073 if (continue_placing) { 00074 /* Make a copy of the place list if we want to keep it afterwards */ 00075 temp_dest_list = o_glist_copy_all (toplevel, 00076 toplevel->page_current->place_list, 00077 temp_dest_list); 00078 } else { 00079 /* Otherwise just take it */ 00080 temp_dest_list = toplevel->page_current->place_list; 00081 toplevel->page_current->place_list = NULL; 00082 } 00083 00084 if (ret_new_objects != NULL) { 00085 *ret_new_objects = g_list_copy (temp_dest_list); 00086 } 00087 00088 o_glist_translate_world(toplevel, w_diff_x, w_diff_y, temp_dest_list); 00089 00090 /* Attach each item back onto the page's object list. Update object 00091 * connectivity and add the new objects to the selection list.*/ 00092 p_current = toplevel->page_current; 00093 00094 for (iter = temp_dest_list; iter != NULL; iter = g_list_next (iter)) { 00095 o_current = iter->data; 00096 00097 s_page_append (toplevel, p_current, o_current); 00098 00099 /* Update object connectivity */ 00100 s_conn_update_object (toplevel, o_current); 00101 connected_objects = s_conn_return_others (connected_objects, o_current); 00102 } 00103 00104 if (hook_name != NULL) { 00105 g_run_hook_object_list (w_current, hook_name, temp_dest_list); 00106 } 00107 00108 o_invalidate_glist (w_current, connected_objects); 00109 g_list_free (connected_objects); 00110 connected_objects = NULL; 00111 00112 toplevel->page_current->CHANGED = 1; 00113 o_invalidate_glist (w_current, temp_dest_list); /* only redraw new objects */ 00114 g_list_free (temp_dest_list); 00115 00116 o_undo_savestate (w_current, UNDO_ALL); 00117 i_update_menus (w_current); 00118 } 00119 00125 void o_place_motion (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00126 { 00127 if (w_current->rubber_visible) 00128 o_place_invalidate_rubber (w_current, FALSE); 00129 w_current->second_wx = w_x; 00130 w_current->second_wy = w_y; 00131 o_place_invalidate_rubber (w_current, TRUE); 00132 w_current->rubber_visible = 1; 00133 } 00134 00135 00168 void o_place_invalidate_rubber (GSCHEM_TOPLEVEL *w_current, int drawing) 00169 { 00170 TOPLEVEL *toplevel = w_current->toplevel; 00171 int diff_x, diff_y; 00172 int left, top, bottom, right; 00173 int s_left, s_top, s_bottom, s_right; 00174 00175 g_return_if_fail (toplevel->page_current->place_list != NULL); 00176 00177 /* If drawing is true, then don't worry about the previous drawing 00178 * method and movement constraints, use with the current settings */ 00179 if (drawing) { 00180 /* Ensure we set this to flag there is "something" supposed to be 00181 * drawn when the invaliate call below causes an expose event. */ 00182 w_current->last_drawb_mode = w_current->actionfeedback_mode; 00183 w_current->drawbounding_action_mode = (w_current->CONTROLKEY) 00184 ? CONSTRAINED : FREE; 00185 } 00186 00187 /* Calculate delta of X-Y positions from buffer's origin */ 00188 diff_x = w_current->second_wx - w_current->first_wx; 00189 diff_y = w_current->second_wy - w_current->first_wy; 00190 00191 /* Adjust the coordinates according to the movement constraints */ 00192 00193 /* Need to update the w_current->{first,second}_w{x,y} coords even 00194 * though we're only invalidating because the move rubberband code 00195 * (which may execute right after this function) expects these 00196 * coordinates to be correct. 00197 */ 00198 if (w_current->drawbounding_action_mode == CONSTRAINED) { 00199 if (abs (diff_x) >= abs (diff_y)) { 00200 w_current->second_wy = w_current->first_wy; 00201 diff_y = 0; 00202 } else { 00203 w_current->second_wx = w_current->first_wx; 00204 diff_x = 0; 00205 } 00206 } 00207 00208 /* Find the bounds of the drawing to be done */ 00209 world_get_object_glist_bounds (toplevel, toplevel->page_current->place_list, 00210 &left, &top, &right, &bottom); 00211 WORLDtoSCREEN (w_current, left + diff_x, top + diff_y, &s_left, &s_top); 00212 WORLDtoSCREEN (w_current, right + diff_x, bottom + diff_y, &s_right, &s_bottom); 00213 00214 o_invalidate_rect (w_current, s_left, s_top, s_right, s_bottom); 00215 } 00216 00217 00252 void o_place_draw_rubber (GSCHEM_TOPLEVEL *w_current, int drawing) 00253 { 00254 TOPLEVEL *toplevel = w_current->toplevel; 00255 int diff_x, diff_y; 00256 int left, top, bottom, right; 00257 00258 g_return_if_fail (toplevel->page_current->place_list != NULL); 00259 00260 /* If drawing is true, then don't worry about the previous drawing 00261 * method and movement constraints, use with the current settings */ 00262 if (drawing) { 00263 w_current->last_drawb_mode = w_current->actionfeedback_mode; 00264 w_current->drawbounding_action_mode = (w_current->CONTROLKEY) 00265 ? CONSTRAINED : FREE; 00266 } 00267 00268 /* Calculate delta of X-Y positions from buffer's origin */ 00269 diff_x = w_current->second_wx - w_current->first_wx; 00270 diff_y = w_current->second_wy - w_current->first_wy; 00271 00272 /* Adjust the coordinates according to the movement constraints */ 00273 if (w_current->drawbounding_action_mode == CONSTRAINED ) { 00274 if (abs(diff_x) >= abs(diff_y)) { 00275 w_current->second_wy = w_current->first_wy; 00276 diff_y = 0; 00277 } else { 00278 w_current->second_wx = w_current->first_wx; 00279 diff_x = 0; 00280 } 00281 } 00282 00283 /* Draw with the appropriate mode */ 00284 if (w_current->last_drawb_mode == BOUNDINGBOX) { 00285 00286 /* Find the bounds of the drawing to be done */ 00287 world_get_object_glist_bounds (toplevel, 00288 toplevel->page_current->place_list, 00289 &left, &top, &right, &bottom); 00290 00291 gschem_cairo_box (w_current, 0, left + diff_x, top + diff_y, 00292 right + diff_x, bottom + diff_y); 00293 00294 gschem_cairo_set_source_color (w_current, 00295 x_color_lookup_dark (BOUNDINGBOX_COLOR)); 00296 gschem_cairo_stroke (w_current, TYPE_SOLID, END_NONE, 0, -1, -1); 00297 } else { 00298 o_glist_draw_place (w_current, diff_x, diff_y, 00299 toplevel->page_current->place_list); 00300 } 00301 00302 /* Save movement constraints and drawing method for any 00303 * corresponding undraw operation. */ 00304 w_current->last_drawb_mode = w_current->actionfeedback_mode; 00305 w_current->drawbounding_action_mode = (w_current->CONTROLKEY) 00306 ? CONSTRAINED : FREE; 00307 } 00308 00309 00315 void o_place_rotate (GSCHEM_TOPLEVEL *w_current) 00316 { 00317 TOPLEVEL *toplevel = w_current->toplevel; 00318 00319 o_glist_rotate_world (toplevel, 00320 w_current->first_wx, w_current->first_wy, 90, 00321 toplevel->page_current->place_list); 00322 00323 00324 /* Run rotate-objects-hook */ 00325 g_run_hook_object_list (w_current, "%rotate-objects-hook", 00326 toplevel->page_current->place_list); 00327 }