Added a new parameter to o_redraw and o_cue_redraw_all,
[geda-gaf/whiteaudio.git] / gschem / src / o_select.c
blob9e3e67cd1f486f87980103b8a5feba5d6eab1b0e
1 /* gEDA - GPL Electronic Design Automation
2 * gschem - gEDA Schematic Capture
3 * Copyright (C) 1998-2000 Ales V. Hvezda
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
19 /*! The code in this file is sometimes not obvious, especially
20 * o_select_object (which implements the selection of objects either
21 * when doing a single or multi select)
23 * Also, there are cases where it looks like there is redundant code, which
24 * could be removed/merged, but I purposely didn't do so to keep the code
25 * readable
27 * the count == 0 stuff really only applies to when you are coming from a
28 * multi select case
30 #include <config.h>
32 #include <math.h>
33 #include <stdio.h>
35 #include <libgeda/libgeda.h>
37 #include "../include/globals.h"
38 #include "../include/x_states.h"
39 #include "../include/prototype.h"
41 #ifdef HAVE_LIBDMALLOC
42 #include <dmalloc.h>
43 #endif
45 /*! \todo Finish function documentation!!!
46 * \brief
47 * \par Function Description
50 void o_select_run_hooks(TOPLEVEL *w_current, OBJECT *o_current, int flag)
53 * Run the select_component_hook if the hook has been defined and we
54 * are selecting a component. This will likely be used for cross probing
55 * between schematics and PCB layout or schematics and simulation results.
57 if ( (scm_hook_empty_p(deselect_all_hook) == SCM_BOOL_F)
58 && flag == 2 )
60 scm_run_hook(deselect_all_hook,
61 scm_cons (g_make_attrib_smob_list(w_current, o_current),
62 SCM_EOL));
66 * Run the select_component_hook if the hook has been defined and we
67 * are selecting a component. This will likely be used for cross probing
68 * between schematics and PCB layout or schematics and simulation results.
70 if ( (scm_hook_empty_p(select_component_hook) == SCM_BOOL_F)
71 && o_current
72 && (o_current->type == OBJ_COMPLEX)
73 && flag == 1 )
75 scm_run_hook(select_component_hook,
76 scm_cons (g_make_attrib_smob_list(w_current, o_current),
77 SCM_EOL));
81 * Run the deselect_component_hook if the hook has been defined and we
82 * are deselecting a component. This will likely be used for cross probing
83 * between schematics and PCB layout or schematics and simulation results.
85 if ( (scm_hook_empty_p(deselect_component_hook) == SCM_BOOL_F)
86 && o_current
87 && (o_current->type == OBJ_COMPLEX)
88 && flag == 0 )
90 scm_run_hook(deselect_component_hook,
91 scm_cons (g_make_attrib_smob_list(w_current, o_current),
92 SCM_EOL));
96 * Run the select_net_hook if the hook has been defined and we
97 * are selecting a net. This will likely be used for cross probing
98 * between schematics and PCB layout or schematics and simulation results.
100 if ( (scm_hook_empty_p(select_net_hook) == SCM_BOOL_F)
101 && o_current
102 && (o_current->type == OBJ_NET)
103 && flag == 1)
105 scm_run_hook(select_net_hook,
106 scm_cons (g_make_attrib_smob_list(w_current, o_current),
107 SCM_EOL));
111 * Run the deselect_net_hook if the hook has been defined and we
112 * are deselecting a net. This will likely be used for cross probing
113 * between schematics and PCB layout or schematics and simulation results.
115 if ( (scm_hook_empty_p(select_net_hook) == SCM_BOOL_F)
116 && o_current
117 && (o_current->type == OBJ_NET)
118 && flag == 0)
120 scm_run_hook(deselect_net_hook,
121 scm_cons (g_make_attrib_smob_list(w_current, o_current),
122 SCM_EOL));
126 /*! \todo Finish function documentation!!!
127 * \brief
128 * \par Function Description
130 * \note
131 * type can be either SINGLE meaning selection is a single mouse click
132 * or it can be MULTIPLE meaning selection is a selection box
134 void o_select_object(TOPLEVEL *w_current, OBJECT *o_current,
135 int type, int count)
137 int SHIFTKEY;
138 int CONTROLKEY;
140 SHIFTKEY = w_current->SHIFTKEY;
141 CONTROLKEY = w_current->CONTROLKEY;
143 #if DEBUG
144 printf("OBJECT id: %d\n", o_current->sid);
145 #endif
147 switch(o_current->selected) {
149 case(FALSE): /* object not selected */
151 switch(SHIFTKEY) { /* shift key pressed? */
153 case(TRUE): /* shift key pressed */
154 /* just fall through */
155 break;
157 case(FALSE):
159 /* condition: first object being added */
160 /* condition: control key not pressed */
161 /* condition: for both multiple and single object added */
162 /* result: remove all objects from selection */
163 if (count == 0 && !CONTROLKEY) {
164 o_select_run_hooks(w_current, NULL, 2);
165 o_selection_remove_most(w_current,
166 w_current->page_current->selection2_head);
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->selection2_head,
175 o_current);
177 break;
180 case(TRUE): /* object was already selected */
182 switch(SHIFTKEY) { /* shift key pressed ? */
184 case(TRUE): /* shift key pressed */
186 /* condition: not doing multiple */
187 /* result: remove object from selection */
188 if (type != MULTIPLE) {
189 o_select_run_hooks(w_current, o_current, 0);
190 o_selection_remove(
191 w_current->page_current->selection2_head,
192 o_current);
195 break;
197 case(FALSE): /* shift key not pressed */
199 /* condition: doing multiple */
200 /* condition: first object being added */
201 /* condition: control key not pressed */
202 /* 1st result: remove all objects from selection */
203 /* 2nd result: add object to selection */
204 if (type == MULTIPLE && count == 0 && !CONTROLKEY) {
205 o_select_run_hooks(w_current, NULL, 2);
206 o_selection_remove_most(w_current,
207 w_current->page_current->selection2_head);
209 o_select_run_hooks(w_current, o_current, 1);
210 o_selection_add(
211 w_current->page_current->selection2_head,
212 o_current);
215 /* condition: doing single object add */
216 /* condition: control key not pressed */
217 /* 1st result: remove all objects from selection */
218 /* 2nd result: add object to selection list */
219 if (type == SINGLE && !CONTROLKEY) {
220 o_select_run_hooks(w_current, NULL, 2);
221 o_selection_remove_most(w_current,
222 w_current->page_current->selection2_head);
224 o_select_run_hooks (w_current, o_current, 1);
225 o_selection_add(
226 w_current->page_current->selection2_head,
227 o_current);
230 if (CONTROLKEY) {
231 o_select_run_hooks(w_current, o_current, 0);
232 o_selection_remove(
233 w_current->page_current->selection2_head,
234 o_current);
237 break;
239 break; /* end object selected switch */
242 /* do the attributes */
243 o_attrib_add_selected(w_current, w_current->page_current->selection2_head,
244 o_current);
246 /* finally redraw object */
247 o_redraw_single(w_current, o_current);
250 /*! \todo Finish function documentation!!!
251 * \brief
252 * \par Function Description
255 void o_select_box_start(TOPLEVEL *w_current, int x, int y)
257 int box_width, box_height;
259 /* don't set these to the passed in x, y */
260 w_current->last_x = w_current->start_x;
261 w_current->last_y = w_current->start_y;
263 box_width = abs(w_current->last_x - w_current->start_x);
264 box_height = abs(w_current->last_y - w_current->start_y);
266 gdk_gc_set_foreground(w_current->xor_gc,
267 x_get_darkcolor(w_current->select_color));
268 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
269 FALSE,
270 w_current->start_x,
271 w_current->start_y,
272 box_width,
273 box_height);
276 /*! \todo Finish function documentation!!!
277 * \brief
278 * \par Function Description
281 void o_select_box_end(TOPLEVEL *w_current, int x, int y)
283 int box_width, box_height;
284 int box_left, box_top;
286 #if 0
287 if (w_current->inside_action == 0) {
288 o_redraw(w_current, w_current->page_current->object_head, TRUE);
289 return;
291 #endif
293 box_width = abs(w_current->last_x - w_current->start_x);
294 box_height = abs(w_current->last_y - w_current->start_y);
296 if( w_current->last_y < w_current->start_y )
297 box_top = w_current->last_y;
298 else
299 box_top = w_current->start_y;
301 if( w_current->last_x < w_current->start_x )
302 box_left = w_current->last_x;
303 else
304 box_left = w_current->start_x;
306 gdk_gc_set_foreground(w_current->xor_gc,
307 x_get_darkcolor(w_current->select_color));
308 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
309 FALSE,
310 box_left,
311 box_top,
312 box_width,
313 box_height);
315 o_select_box_search(w_current);
318 /*! \todo Finish function documentation!!!
319 * \brief
320 * \par Function Description
323 void o_select_box_rubberband(TOPLEVEL *w_current, int x, int y)
325 int box_width, box_height;
326 int box_left, box_top;
328 #if 0
329 if (w_current->inside_action == 0) {
330 o_redraw(w_current, w_current->page_current->object_head, TRUE);
331 return;
333 #endif
335 box_width = abs(w_current->last_x - w_current->start_x);
336 box_height = abs(w_current->last_y - w_current->start_y);
338 if( w_current->last_y < w_current->start_y )
339 box_top = w_current->last_y;
340 else
341 box_top = w_current->start_y;
343 if( w_current->last_x < w_current->start_x )
344 box_left = w_current->last_x;
345 else
346 box_left = w_current->start_x;
349 gdk_gc_set_foreground(w_current->xor_gc,
350 x_get_darkcolor(w_current->select_color));
351 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
352 FALSE,
353 box_left ,
354 box_top ,
355 box_width ,
356 box_height);
359 /* removed fix_x, fix_y to unrestrict sels */
360 w_current->last_x = (int) x;
361 w_current->last_y = (int) y;
363 box_width = abs(w_current->last_x - w_current->start_x);
364 box_height = abs(w_current->last_y - w_current->start_y);
366 if( w_current->last_y < w_current->start_y )
367 box_top = w_current->last_y;
368 else
369 box_top = w_current->start_y;
371 if( w_current->last_x < w_current->start_x )
372 box_left = w_current->last_x;
373 else
374 box_left = w_current->start_x;
376 gdk_draw_rectangle(w_current->window, w_current->xor_gc,
377 FALSE,
378 box_left,
379 box_top,
380 box_width,
381 box_height);
385 /*! \todo Finish function documentation!!!
386 * \brief
387 * \par Function Description
390 void o_select_box_search(TOPLEVEL *w_current)
392 OBJECT *o_current=NULL;
393 int count = 0; /* object count */
394 int SHIFTKEY = w_current->SHIFTKEY;
396 int tmp;
398 if( w_current->last_x < w_current->start_x ) {
399 tmp = w_current->last_x;
400 w_current->last_x = w_current->start_x;
401 w_current->start_x = tmp;
404 if( w_current->last_y < w_current->start_y ) {
405 tmp = w_current->last_y;
406 w_current->last_y = w_current->start_y;
407 w_current->start_y = tmp;
410 o_current = w_current->page_current->object_head;
412 while (o_current != NULL) {
413 /* only select visible objects */
414 if (o_current->type != OBJ_HEAD &&
415 (o_current->visibility == VISIBLE ||
416 (o_current->visibility == INVISIBLE && w_current->show_hidden_text))) {
417 if ( (o_current->left >= w_current->start_x &&
418 o_current->top >= w_current->start_y) &&
419 (o_current->left >= w_current->start_x &&
420 o_current->bottom <= w_current->last_y) &&
421 (o_current->right <= w_current->last_x &&
422 o_current->top >= w_current->start_y ) &&
423 (o_current->right <= w_current->last_x &&
424 o_current->bottom <= w_current->last_y) ) {
426 o_select_object(w_current, o_current,
427 MULTIPLE, count);
428 count++;
431 o_current = o_current->next;
434 /* if there were no objects to be found in select box, count will be */
435 /* zero, and you need to deselect anything remaining (unless the shift */
436 /* key was pressed */
437 if (count == 0 && !SHIFTKEY) {
438 o_select_run_hooks(w_current, NULL, 2);
439 o_selection_remove_most(w_current,
440 w_current->page_current->selection2_head);
442 i_update_menus(w_current);
445 /* This is a wrapper for o_selection_return_first_object */
446 /* This function always looks at the current page selection list */
447 OBJECT *o_select_return_first_object(TOPLEVEL *w_current)
449 return(o_selection_return_first_object(w_current->page_current->
450 selection2_head));
453 /*! \todo Finish function documentation!!!
454 * \brief
455 * \par Function Description
457 * \return TRUE if the selection list is not empty, otherwise false.
458 * also make sure item is valid
460 int o_select_selected(TOPLEVEL *w_current)
462 SELECTION *head;
464 head = w_current->page_current->selection2_head;
465 if (head) {
466 if (head->next) {
467 if (head->next->selected_object) {
468 return(TRUE);
472 return(FALSE);
475 /*! \todo Finish function documentation!!!
476 * \brief
477 * \par Function Description
480 void o_select_unselect_all(TOPLEVEL *w_current)
482 o_select_run_hooks(w_current, NULL, 2);
483 o_selection_remove_most(w_current,
484 w_current->page_current->selection2_head);