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
27 * the count == 0 stuff really only applies to when you are coming from a
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
45 /*! \todo Finish function documentation!!!
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
)
60 scm_run_hook(deselect_all_hook
,
61 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
72 && (o_current
->type
== OBJ_COMPLEX
)
75 scm_run_hook(select_component_hook
,
76 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
87 && (o_current
->type
== OBJ_COMPLEX
)
90 scm_run_hook(deselect_component_hook
,
91 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
102 && (o_current
->type
== OBJ_NET
)
105 scm_run_hook(select_net_hook
,
106 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
117 && (o_current
->type
== OBJ_NET
)
120 scm_run_hook(deselect_net_hook
,
121 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
126 /*! \todo Finish function documentation!!!
128 * \par Function Description
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
,
140 SHIFTKEY
= w_current
->SHIFTKEY
;
141 CONTROLKEY
= w_current
->CONTROLKEY
;
144 printf("OBJECT id: %d\n", o_current
->sid
);
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 */
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
);
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
,
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);
191 w_current
->page_current
->selection2_head
,
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);
211 w_current
->page_current
->selection2_head
,
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);
226 w_current
->page_current
->selection2_head
,
231 o_select_run_hooks(w_current
, o_current
, 0);
233 w_current
->page_current
->selection2_head
,
239 break; /* end object selected switch */
242 /* do the attributes */
243 o_attrib_add_selected(w_current
, w_current
->page_current
->selection2_head
,
246 /* finally redraw object */
247 o_redraw_single(w_current
, o_current
);
250 /*! \todo Finish function documentation!!!
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
,
276 /*! \todo Finish function documentation!!!
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
;
287 if (w_current
->inside_action
== 0) {
288 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
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
;
299 box_top
= w_current
->start_y
;
301 if( w_current
->last_x
< w_current
->start_x
)
302 box_left
= w_current
->last_x
;
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
,
315 o_select_box_search(w_current
);
318 /*! \todo Finish function documentation!!!
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
;
329 if (w_current
->inside_action
== 0) {
330 o_redraw(w_current
, w_current
->page_current
->object_head
, TRUE
);
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
;
341 box_top
= w_current
->start_y
;
343 if( w_current
->last_x
< w_current
->start_x
)
344 box_left
= w_current
->last_x
;
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
,
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
;
369 box_top
= w_current
->start_y
;
371 if( w_current
->last_x
< w_current
->start_x
)
372 box_left
= w_current
->last_x
;
374 box_left
= w_current
->start_x
;
376 gdk_draw_rectangle(w_current
->window
, w_current
->xor_gc
,
385 /*! \todo Finish function documentation!!!
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
;
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
,
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
->
453 /*! \todo Finish function documentation!!!
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
)
464 head
= w_current
->page_current
->selection2_head
;
467 if (head
->next
->selected_object
) {
475 /*! \todo Finish function documentation!!!
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
);