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 00022 #include <math.h> 00023 #include <stdio.h> 00024 00025 #include "gschem.h" 00026 00027 #ifdef HAVE_LIBDMALLOC 00028 #include <dmalloc.h> 00029 #endif 00030 00031 00047 static gboolean 00048 is_object_hit (GSCHEM_TOPLEVEL *w_current, OBJECT *object, 00049 int w_x, int w_y, int w_slack) 00050 { 00051 if (!object->selectable) 00052 return FALSE; 00053 00054 /* We can't hit invisible (text) objects unless show_hidden_text is active. 00055 */ 00056 if (!o_is_visible (w_current->toplevel, object) && 00057 !w_current->toplevel->show_hidden_text) 00058 return FALSE; 00059 00060 /* Do a coarse test first to avoid computing distances for objects ouside 00061 * of the hit range. 00062 */ 00063 if (!inside_region (object->w_left - w_slack, object->w_top - w_slack, 00064 object->w_right + w_slack, object->w_bottom + w_slack, 00065 w_x, w_y)) 00066 return FALSE; 00067 00068 return (o_shortest_distance (object, w_x, w_y) < w_slack); 00069 } 00070 00071 00088 static gboolean 00089 find_single_object (GSCHEM_TOPLEVEL *w_current, OBJECT *object, 00090 int w_x, int w_y, int w_slack, 00091 int change_selection) 00092 { 00093 if (!is_object_hit (w_current, object, w_x, w_y, w_slack)) 00094 return FALSE; 00095 00096 if (change_selection) { 00097 /* FIXME: should this be moved to o_select_object()? (Werner) */ 00098 if (object->type == OBJ_NET && w_current->net_selection_mode) 00099 o_select_connected_nets (w_current, object); 00100 else 00101 o_select_object (w_current, object, SINGLE, 0); /* 0 is count */ 00102 } 00103 00104 w_current->toplevel->page_current->object_lastplace = object; 00105 i_update_menus (w_current); 00106 return TRUE; 00107 } 00108 00109 00127 gboolean o_find_object (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y, 00128 gboolean change_selection) 00129 { 00130 TOPLEVEL *toplevel = w_current->toplevel; 00131 int w_slack; 00132 const GList *iter = NULL; 00133 00134 w_slack = WORLDabs (w_current, w_current->select_slack_pixels); 00135 00136 /* Decide whether to iterate over all object or start at the last 00137 found object. If there is more than one object below the 00138 (w_x/w_y) position, this will select the next object below the 00139 position point. You can change the selected object by clicking 00140 at the same place multiple times. */ 00141 if (toplevel->page_current->object_lastplace != NULL) { 00142 /* NB: g_list_find doesn't declare its input const, so we cast */ 00143 iter = g_list_find ((GList *)s_page_objects (toplevel->page_current), 00144 toplevel->page_current->object_lastplace); 00145 iter = g_list_next (iter); 00146 } 00147 00148 /* do first search (if we found any objects after the last found object) */ 00149 while (iter != NULL) { 00150 OBJECT *o_current = iter->data; 00151 if (find_single_object (w_current, o_current, 00152 w_x, w_y, w_slack, change_selection)) { 00153 return TRUE; 00154 } 00155 iter = g_list_next (iter); 00156 } 00157 00158 /* now search from the beginning up until the object_lastplace */ 00159 for (iter = s_page_objects (toplevel->page_current); 00160 iter != NULL; iter = g_list_next (iter)) { 00161 OBJECT *o_current = iter->data; 00162 if (find_single_object (w_current, o_current, 00163 w_x, w_y, w_slack, change_selection)) { 00164 return TRUE; 00165 } 00166 /* break once we've inspected up to where we started the first loop */ 00167 if (o_current == toplevel->page_current->object_lastplace) 00168 break; 00169 } 00170 00171 /* didn't find anything.... reset lastplace */ 00172 toplevel->page_current->object_lastplace = NULL; 00173 00174 /* deselect everything only if shift key isn't pressed and 00175 the caller allows it */ 00176 if (change_selection && (!w_current->SHIFTKEY)) { 00177 o_select_unselect_all (w_current); 00178 } 00179 00180 i_update_menus(w_current); 00181 return FALSE; 00182 } 00183 00189 gboolean 00190 o_find_selected_object (GSCHEM_TOPLEVEL *w_current, int w_x, int w_y) 00191 { 00192 TOPLEVEL *toplevel = w_current->toplevel; 00193 int w_slack = WORLDabs (w_current, w_current->select_slack_pixels); 00194 GList *s_current; 00195 00196 for (s_current = geda_list_get_glist (toplevel->page_current->selection_list); 00197 s_current != NULL; s_current = g_list_next (s_current)) { 00198 OBJECT *o_current = s_current->data; 00199 00200 if (is_object_hit (w_current, o_current, w_x, w_y, w_slack)) 00201 return TRUE; 00202 } 00203 00204 return FALSE; 00205 }