Moved 3 rc promotion keywords from gschem into libgeda (fix for bug#1748143)
[geda-gaf/peter-b.git] / gschem / src / o_select.c
blob388e268b6d983209a5f771ff9f170458d39b3d7d
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2007 Ales Hvezda
4 * Copyright (C) 1998-2007 gEDA Contributors (see ChangeLog for details)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
20 /*! The code in this file is sometimes not obvious, especially
21 * o_select_object (which implements the selection of objects either
22 * when doing a single or multi select)
24 * Also, there are cases where it looks like there is redundant code, which
25 * could be removed/merged, but I purposely didn't do so to keep the code
26 * readable
28 * the count == 0 stuff really only applies to when you are coming from a
29 * multi select case
31 #include <config.h>
33 #include <math.h>
34 #include <stdio.h>
36 #include <libgeda/libgeda.h>
38 #include "../include/globals.h"
39 #include "../include/x_states.h"
40 #include "../include/prototype.h"
42 #ifdef HAVE_LIBDMALLOC
43 #include <dmalloc.h>
44 #endif
46 /*! \todo Finish function documentation!!!
47 * \brief
48 * \par Function Description
51 void o_select_run_hooks(TOPLEVEL *w_current, OBJECT *o_current, int flag)
54 * Run the select_component_hook if the hook has been defined and we
55 * are selecting a component. This will likely be used for cross probing
56 * between schematics and PCB layout or schematics and simulation results.
58 if ( (scm_hook_empty_p(deselect_all_hook) == SCM_BOOL_F)
59 && flag == 2 )
61 scm_run_hook(deselect_all_hook,
62 scm_cons (g_make_attrib_smob_list(w_current, o_current),
63 SCM_EOL));
67 * Run the select_component_hook if the hook has been defined and we
68 * are selecting a component. This will likely be used for cross probing
69 * between schematics and PCB layout or schematics and simulation results.
71 if ( (scm_hook_empty_p(select_component_hook) == SCM_BOOL_F)
72 && o_current
73 && (o_current->type == OBJ_COMPLEX)
74 && flag == 1 )
76 scm_run_hook(select_component_hook,
77 scm_cons (g_make_attrib_smob_list(w_current, o_current),
78 SCM_EOL));
82 * Run the deselect_component_hook if the hook has been defined and we
83 * are deselecting a component. This will likely be used for cross probing
84 * between schematics and PCB layout or schematics and simulation results.
86 if ( (scm_hook_empty_p(deselect_component_hook) == SCM_BOOL_F)
87 && o_current
88 && (o_current->type == OBJ_COMPLEX)
89 && flag == 0 )
91 scm_run_hook(deselect_component_hook,
92 scm_cons (g_make_attrib_smob_list(w_current, o_current),
93 SCM_EOL));
97 * Run the select_net_hook if the hook has been defined and we
98 * are selecting a net. This will likely be used for cross probing
99 * between schematics and PCB layout or schematics and simulation results.
101 if ( (scm_hook_empty_p(select_net_hook) == SCM_BOOL_F)
102 && o_current
103 && (o_current->type == OBJ_NET)
104 && flag == 1)
106 scm_run_hook(select_net_hook,
107 scm_cons (g_make_attrib_smob_list(w_current, o_current),
108 SCM_EOL));
112 * Run the deselect_net_hook if the hook has been defined and we
113 * are deselecting a net. This will likely be used for cross probing
114 * between schematics and PCB layout or schematics and simulation results.
116 if ( (scm_hook_empty_p(select_net_hook) == SCM_BOOL_F)
117 && o_current
118 && (o_current->type == OBJ_NET)
119 && flag == 0)
121 scm_run_hook(deselect_net_hook,
122 scm_cons (g_make_attrib_smob_list(w_current, o_current),
123 SCM_EOL));
127 /*! \todo Finish function documentation!!!
128 * \brief
129 * \par Function Description
131 * \note
132 * type can be either SINGLE meaning selection is a single mouse click
133 * or it can be MULTIPLE meaning selection is a selection box
135 void o_select_object(TOPLEVEL *w_current, OBJECT *o_current,
136 int type, int count)
138 int SHIFTKEY;
139 int CONTROLKEY;
141 SHIFTKEY = w_current->SHIFTKEY;
142 CONTROLKEY = w_current->CONTROLKEY;
144 #if DEBUG
145 printf("OBJECT id: %d\n", o_current->sid);
146 #endif
148 switch(o_current->selected) {
150 case(FALSE): /* object not selected */
152 switch(SHIFTKEY) { /* shift key pressed? */
154 case(TRUE): /* shift key pressed */
155 /* just fall through */
156 break;
158 case(FALSE):
160 /* condition: first object being added */
161 /* condition: control key not pressed */
162 /* condition: for both multiple and single object added */
163 /* result: remove all objects from selection */
164 if (count == 0 && !CONTROLKEY) {
165 o_select_run_hooks( w_current, NULL, 2 );
166 o_selection_unselect_list (w_current,w_current->page_current->selection_list);
168 break;
170 } /* end shift key switch */
172 /* object not select, add it to the selection list */
173 o_select_run_hooks( w_current, o_current, 1 );
174 o_selection_add( w_current->page_current->selection_list, o_current);
176 break;
179 case(TRUE): /* object was already selected */
181 switch(SHIFTKEY) { /* shift key pressed ? */
183 case(TRUE): /* shift key pressed */
185 /* condition: not doing multiple */
186 /* result: remove object from selection */
187 if (type != MULTIPLE) {
188 o_select_run_hooks( w_current, o_current, 0 );
189 o_selection_remove( w_current->page_current->selection_list, o_current );
192 break;
194 case(FALSE): /* shift key not pressed */
196 /* condition: doing multiple */
197 /* condition: first object being added */
198 /* condition: control key not pressed */
199 /* 1st result: remove all objects from selection */
200 /* 2nd result: add object to selection */
201 if (type == MULTIPLE && count == 0 && !CONTROLKEY) {
202 o_select_run_hooks( w_current, NULL, 2 );
203 o_selection_unselect_list (w_current, w_current->page_current->selection_list );
205 o_select_run_hooks( w_current, o_current, 1 );
206 o_selection_add( w_current->page_current->selection_list, o_current);
209 /* condition: doing single object add */
210 /* condition: control key not pressed */
211 /* 1st result: remove all objects from selection */
212 /* 2nd result: add object to selection list */
213 if (type == SINGLE && !CONTROLKEY) {
214 o_select_run_hooks( w_current, NULL, 2 );
215 o_selection_unselect_list( w_current, w_current->page_current->selection_list );
217 o_select_run_hooks (w_current, o_current, 1);
218 o_selection_add( w_current->page_current->selection_list, o_current);
221 if (CONTROLKEY) {
222 o_select_run_hooks(w_current, o_current, 0);
223 o_selection_remove( w_current->page_current->selection_list, o_current);
226 break;
228 break; /* end object selected switch */
231 /* do the attributes */
232 o_attrib_add_selected(w_current, w_current->page_current->selection_list, o_current);
234 /* finally redraw object */
235 o_redraw_single(w_current, o_current);
238 /*! \todo Finish function documentation!!!
239 * \brief
240 * \par Function Description
243 void o_select_box_start(TOPLEVEL *w_current, int x, int y)
245 int box_width, box_height;
247 /* don't set these to the passed in x, y */
248 w_current->last_x = w_current->start_x;
249 w_current->last_y = w_current->start_y;
251 box_width = abs(w_current->last_x - w_current->start_x);
252 box_height = abs(w_current->last_y - w_current->start_y);
254 gdk_gc_set_foreground(w_current->xor_gc,
255 x_get_darkcolor(w_current->select_color));
256 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
257 FALSE,
258 w_current->start_x,
259 w_current->start_y,
260 box_width,
261 box_height);
264 /*! \todo Finish function documentation!!!
265 * \brief
266 * \par Function Description
269 void o_select_box_end(TOPLEVEL *w_current, int x, int y)
271 int box_width, box_height;
272 int box_left, box_top;
274 box_width = abs(w_current->last_x - w_current->start_x);
275 box_height = abs(w_current->last_y - w_current->start_y);
277 if( w_current->last_y < w_current->start_y )
278 box_top = w_current->last_y;
279 else
280 box_top = w_current->start_y;
282 if( w_current->last_x < w_current->start_x )
283 box_left = w_current->last_x;
284 else
285 box_left = w_current->start_x;
287 gdk_gc_set_foreground(w_current->xor_gc,
288 x_get_darkcolor(w_current->select_color));
289 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
290 FALSE,
291 box_left,
292 box_top,
293 box_width,
294 box_height);
296 o_select_box_search(w_current);
299 /*! \todo Finish function documentation!!!
300 * \brief
301 * \par Function Description
304 void o_select_box_rubberband(TOPLEVEL *w_current, int x, int y)
306 int box_width, box_height;
307 int box_left, box_top;
309 box_width = abs(w_current->last_x - w_current->start_x);
310 box_height = abs(w_current->last_y - w_current->start_y);
312 if( w_current->last_y < w_current->start_y )
313 box_top = w_current->last_y;
314 else
315 box_top = w_current->start_y;
317 if( w_current->last_x < w_current->start_x )
318 box_left = w_current->last_x;
319 else
320 box_left = w_current->start_x;
323 gdk_gc_set_foreground(w_current->xor_gc,
324 x_get_darkcolor(w_current->select_color));
325 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
326 FALSE,
327 box_left ,
328 box_top ,
329 box_width ,
330 box_height);
333 /* removed fix_x, fix_y to unrestrict sels */
334 w_current->last_x = (int) x;
335 w_current->last_y = (int) y;
337 box_width = abs(w_current->last_x - w_current->start_x);
338 box_height = abs(w_current->last_y - w_current->start_y);
340 if( w_current->last_y < w_current->start_y )
341 box_top = w_current->last_y;
342 else
343 box_top = w_current->start_y;
345 if( w_current->last_x < w_current->start_x )
346 box_left = w_current->last_x;
347 else
348 box_left = w_current->start_x;
350 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
351 FALSE,
352 box_left,
353 box_top,
354 box_width,
355 box_height);
359 /*! \todo Finish function documentation!!!
360 * \brief
361 * \par Function Description
364 void o_select_box_search(TOPLEVEL *w_current)
366 OBJECT *o_current=NULL;
367 int count = 0; /* object count */
368 int SHIFTKEY = w_current->SHIFTKEY;
369 int w_start_x, w_start_y, w_last_x, w_last_y;
371 int tmp;
373 if( w_current->last_x < w_current->start_x ) {
374 tmp = w_current->last_x;
375 w_current->last_x = w_current->start_x;
376 w_current->start_x = tmp;
379 if( w_current->last_y < w_current->start_y ) {
380 tmp = w_current->last_y;
381 w_current->last_y = w_current->start_y;
382 w_current->start_y = tmp;
385 SCREENtoWORLD( w_current, w_current->start_x, w_current->start_y, &w_start_x, &w_start_y );
386 SCREENtoWORLD( w_current, w_current->last_x, w_current->last_y, &w_last_x, &w_last_y );
388 o_current = w_current->page_current->object_head;
390 while (o_current != NULL) {
391 /* only select visible objects */
392 if (o_current->type != OBJ_HEAD &&
393 (o_current->visibility == VISIBLE ||
394 (o_current->visibility == INVISIBLE && w_current->show_hidden_text))) {
396 if ( o_current->w_left >= w_start_x &&
397 o_current->w_right <= w_last_x &&
398 o_current->w_top >= w_last_y &&
399 o_current->w_bottom <= w_start_y ) {
401 o_select_object(w_current, o_current, MULTIPLE, count);
402 count++;
405 o_current = o_current->next;
408 /* if there were no objects to be found in select box, count will be */
409 /* zero, and you need to deselect anything remaining (unless the shift */
410 /* key was pressed */
411 if (count == 0 && !SHIFTKEY) {
412 o_select_run_hooks( w_current, NULL, 2 );
413 o_selection_unselect_list( w_current, w_current->page_current->selection_list );
415 i_update_menus(w_current);
418 /* This is a wrapper for o_selection_return_first_object */
419 /* This function always looks at the current page selection list */
420 OBJECT *o_select_return_first_object(TOPLEVEL *w_current)
422 if (! (w_current && w_current->page_current && geda_list_get_glist( w_current->page_current->selection_list )))
423 return NULL;
424 else
425 return (OBJECT *)g_list_first( geda_list_get_glist( w_current->page_current->selection_list ))->data;
428 /*! \todo Finish function documentation!!!
429 * \brief
430 * \par Function Description
432 * \return TRUE if the selection list is not empty, otherwise false.
433 * also make sure item is valid
435 int o_select_selected(TOPLEVEL *w_current)
437 if ( geda_list_get_glist( w_current->page_current->selection_list )) {
438 return(TRUE);
440 return(FALSE);
443 /*! \todo Finish function documentation!!!
444 * \brief
445 * \par Function Description
448 void o_select_unselect_all(TOPLEVEL *w_current)
450 o_select_run_hooks( w_current, NULL, 2 );
451 o_selection_unselect_list( w_current, w_current->page_current->selection_list );
454 /*! \todo Finish function documentation!!!
455 * \brief
456 * \par Function Description
459 void
460 o_select_move_to_place_list(TOPLEVEL *w_current)
462 GList *selection;
463 OBJECT *o_current;
465 selection = geda_list_get_glist( w_current->page_current->selection_list );
467 if (!selection) {
468 return;
471 while (selection) {
472 o_current = (OBJECT *) selection->data;
473 if (o_current) {
474 w_current->page_current->complex_place_list = g_list_append(w_current->page_current->complex_place_list,
475 o_current);
477 selection = selection->next;