gschem

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