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
28 * the count == 0 stuff really only applies to when you are coming from a
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
46 /*! \todo Finish function documentation!!!
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
)
61 scm_run_hook(deselect_all_hook
,
62 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
73 && (o_current
->type
== OBJ_COMPLEX
)
76 scm_run_hook(select_component_hook
,
77 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
88 && (o_current
->type
== OBJ_COMPLEX
)
91 scm_run_hook(deselect_component_hook
,
92 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
103 && (o_current
->type
== OBJ_NET
)
106 scm_run_hook(select_net_hook
,
107 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
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
)
118 && (o_current
->type
== OBJ_NET
)
121 scm_run_hook(deselect_net_hook
,
122 scm_cons (g_make_attrib_smob_list(w_current
, o_current
),
127 /*! \todo Finish function documentation!!!
129 * \par Function Description
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
,
141 SHIFTKEY
= w_current
->SHIFTKEY
;
142 CONTROLKEY
= w_current
->CONTROLKEY
;
145 printf("OBJECT id: %d\n", o_current
->sid
);
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 */
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
);
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
);
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
);
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
);
222 o_select_run_hooks(w_current
, o_current
, 0);
223 o_selection_remove( w_current
->page_current
->selection_list
, o_current
);
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!!!
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
,
264 /*! \todo Finish function documentation!!!
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
;
280 box_top
= w_current
->start_y
;
282 if( w_current
->last_x
< w_current
->start_x
)
283 box_left
= w_current
->last_x
;
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
,
296 o_select_box_search(w_current
);
299 /*! \todo Finish function documentation!!!
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
;
315 box_top
= w_current
->start_y
;
317 if( w_current
->last_x
< w_current
->start_x
)
318 box_left
= w_current
->last_x
;
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
,
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
;
343 box_top
= w_current
->start_y
;
345 if( w_current
->last_x
< w_current
->start_x
)
346 box_left
= w_current
->last_x
;
348 box_left
= w_current
->start_x
;
350 gdk_draw_rectangle(w_current
->window
, w_current
->xor_gc
,
359 /*! \todo Finish function documentation!!!
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
;
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
);
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
)))
425 return (OBJECT
*)g_list_first( geda_list_get_glist( w_current
->page_current
->selection_list
))->data
;
428 /*! \todo Finish function documentation!!!
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
)) {
443 /*! \todo Finish function documentation!!!
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!!!
456 * \par Function Description
460 o_select_move_to_place_list(TOPLEVEL
*w_current
)
465 selection
= geda_list_get_glist( w_current
->page_current
->selection_list
);
472 o_current
= (OBJECT
*) selection
->data
;
474 w_current
->page_current
->complex_place_list
= g_list_append(w_current
->page_current
->complex_place_list
,
477 selection
= selection
->next
;