1 /* Dia -- an diagram creation/manipulation program
2 * Copyright (C) 1998 Alexander Larsson
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 /* select.c -- callbacks to implement the Select menu */
27 #include "object_ops.h"
29 enum SelectionStyle selection_style
= SELECT_REPLACE
;
32 select_all_callback(gpointer data
, guint action
, GtkWidget
*widget
)
36 DDisplay
* ddisp
= ddisplay_active();
41 objects
= dia
->data
->active_layer
->objects
;
43 while (objects
!= NULL
) {
44 DiaObject
*obj
= (DiaObject
*)objects
->data
;
46 if (!diagram_is_selected(dia
, obj
))
47 diagram_select(dia
, obj
);
49 objects
= g_list_next(objects
);
52 ddisplay_do_update_menu_sensitivity(ddisp
);
53 object_add_updates_list(dia
->data
->selected
, dia
);
58 select_none_callback(gpointer data
, guint action
, GtkWidget
*widget
)
61 DDisplay
* ddisp
= ddisplay_active();
66 diagram_remove_all_selected(dia
, TRUE
);
68 ddisplay_do_update_menu_sensitivity(ddisp
);
69 object_add_updates_list(dia
->data
->selected
, dia
);
74 select_invert_callback(gpointer data
, guint action
, GtkWidget
*widget
)
78 DDisplay
* ddisp
= ddisplay_active();
83 tmp
= dia
->data
->active_layer
->objects
;
85 for (; tmp
!= NULL
; tmp
= g_list_next(tmp
)) {
86 DiaObject
*obj
= (DiaObject
*)tmp
->data
;
88 if (!diagram_is_selected(dia
, obj
))
89 diagram_select(dia
, obj
);
91 diagram_unselect_object(dia
, obj
);
94 ddisplay_do_update_menu_sensitivity(ddisp
);
95 object_add_updates_list(dia
->data
->selected
, dia
);
100 /** Select objects that are directly connected to the currently selected
101 * objects, but only in the active layer.
104 select_connected_callback(gpointer data
, guint action
, GtkWidget
*widget
)
107 DDisplay
* ddisp
= ddisplay_active();
108 GList
*objects
, *tmp
;
111 dia
= ddisp
->diagram
;
113 objects
= dia
->data
->selected
;
115 for (tmp
= objects
; tmp
!= NULL
; tmp
= g_list_next(tmp
)) {
116 DiaObject
*obj
= (DiaObject
*)tmp
->data
;
119 for (i
= 0; i
< obj
->num_handles
; i
++) {
120 Handle
*handle
= obj
->handles
[i
];
122 if (handle
->connected_to
!= NULL
&&
123 handle
->connected_to
->object
->parent_layer
== dia
->data
->active_layer
) {
124 if (!diagram_is_selected(dia
, handle
->connected_to
->object
)) {
125 diagram_select(dia
, handle
->connected_to
->object
);
131 for (tmp
= objects
; tmp
!= NULL
; tmp
= tmp
->next
) {
132 DiaObject
*obj
= (DiaObject
*)tmp
->data
;
135 for (i
= 0; i
< obj
->num_connections
; i
++) {
136 ConnectionPoint
*connection
= obj
->connections
[i
];
137 GList
*conns
= connection
->connected
;
139 for (; conns
!= NULL
; conns
= g_list_next(conns
)) {
140 DiaObject
*obj2
= (DiaObject
*)conns
->data
;
142 if (obj2
->parent_layer
== dia
->data
->active_layer
143 && !diagram_is_selected(dia
, obj2
)) {
144 diagram_select(dia
, obj2
);
150 ddisplay_do_update_menu_sensitivity(ddisp
);
151 object_add_updates_list(dia
->data
->selected
, dia
);
156 select_transitively(Diagram
*dia
, DiaObject
*obj
)
159 /* Do breadth-first to avoid overly large stack */
160 GList
*newly_selected
= NULL
;
162 for (i
= 0; i
< obj
->num_handles
; i
++) {
163 Handle
*handle
= obj
->handles
[i
];
165 if (handle
->connected_to
!= NULL
&&
166 handle
->connected_to
->object
->parent_layer
== dia
->data
->active_layer
) {
167 if (!diagram_is_selected(dia
, handle
->connected_to
->object
)) {
168 diagram_select(dia
, handle
->connected_to
->object
);
169 newly_selected
= g_list_prepend(newly_selected
, handle
->connected_to
->object
);
174 for (i
= 0; i
< obj
->num_connections
; i
++) {
175 ConnectionPoint
*connection
= obj
->connections
[i
];
176 GList
*conns
= connection
->connected
;
178 for (; conns
!= NULL
; conns
= g_list_next(conns
)) {
179 DiaObject
*obj2
= (DiaObject
*)conns
->data
;
181 if (obj2
->parent_layer
== dia
->data
->active_layer
182 && !diagram_is_selected(dia
, obj2
)) {
183 diagram_select(dia
, obj2
);
184 newly_selected
= g_list_prepend(newly_selected
, obj2
);
189 while (newly_selected
!= NULL
) {
190 select_transitively(dia
, (DiaObject
*)newly_selected
->data
);
191 newly_selected
= g_list_next(newly_selected
);
195 /** Select objects that are in any way connected with a currently selected
196 * object, but only in the active layer.
199 select_transitive_callback(gpointer data
, guint action
, GtkWidget
*widget
)
201 DDisplay
*ddisp
= ddisplay_active();
203 GList
*objects
, *tmp
;
206 dia
= ddisp
->diagram
;
208 objects
= dia
->data
->selected
;
210 for (tmp
= objects
; tmp
!= NULL
; tmp
= g_list_next(tmp
)) {
211 select_transitively(dia
, (DiaObject
*)tmp
->data
);
214 ddisplay_do_update_menu_sensitivity(ddisp
);
215 object_add_updates_list(dia
->data
->selected
, dia
);
220 select_same_type_callback(gpointer data
, guint action
, GtkWidget
*widget
)
222 /* For now, do a brute force version: Check vs. all earlier selected.
223 Later, we should really sort the selecteds first to avoid n^2 */
224 DDisplay
*ddisp
= ddisplay_active();
226 GList
*objects
, *tmp
, *tmp2
;
229 dia
= ddisp
->diagram
;
231 tmp
= dia
->data
->active_layer
->objects
;
233 objects
= dia
->data
->selected
;
235 for (; tmp
!= NULL
; tmp
= g_list_next(tmp
)) {
236 DiaObject
*obj
= (DiaObject
*)tmp
->data
;
238 if (!diagram_is_selected(dia
, obj
)) {
239 for (tmp2
= objects
; tmp2
!= NULL
; tmp2
= g_list_next(tmp2
)) {
240 DiaObject
*obj2
= (DiaObject
*)tmp2
->data
;
242 if (obj
->type
== obj2
->type
) {
243 diagram_select(dia
, obj
);
250 ddisplay_do_update_menu_sensitivity(ddisp
);
251 object_add_updates_list(dia
->data
->selected
, dia
);
256 select_style_callback(gpointer data
, guint action
, GtkWidget
*widget
)
258 if (ddisplay_active () == NULL
) return;
260 /* simply set the selection style to the value of `action' */
261 selection_style
= action
;