gschem

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