New group work, and utility funcs.
[dia.git] / app / select.c
blob428a8f24dcfde591c0c3a4b4617e11f9cb13812a
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 */
20 #include <config.h>
22 #include <assert.h>
24 #include "select.h"
25 #include "menus.h"
26 #include "intl.h"
27 #include "object_ops.h"
29 enum SelectionStyle selection_style = SELECT_REPLACE;
31 void
32 select_all_callback(gpointer data, guint action, GtkWidget *widget)
34 Diagram *dia;
35 GList *objects;
36 DDisplay * ddisp = ddisplay_active();
38 if (!ddisp) return;
39 dia = ddisp->diagram;
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);
50 objects = g_list_next(objects);
53 ddisplay_do_update_menu_sensitivity(ddisp);
54 object_add_updates_list(dia->data->selected, dia);
55 diagram_flush(dia);
58 void
59 select_none_callback(gpointer data, guint action, GtkWidget *widget)
61 Diagram * dia;
62 DDisplay * ddisp = ddisplay_active();
64 if (!ddisp) return;
65 dia = ddisp->diagram;
67 diagram_remove_all_selected(dia, TRUE);
69 ddisplay_do_update_menu_sensitivity(ddisp);
70 object_add_updates_list(dia->data->selected, dia);
71 diagram_flush(dia);
74 void
75 select_invert_callback(gpointer data, guint action, GtkWidget *widget)
77 Diagram *dia;
78 GList *tmp;
79 DDisplay * ddisp = ddisplay_active();
81 if (!ddisp) return;
82 dia = ddisp->diagram;
84 tmp = dia->data->active_layer->objects;
86 for (; tmp != NULL; tmp = g_list_next(tmp)) {
87 DiaObject *obj = (DiaObject *)tmp->data;
89 if (!diagram_is_selected(dia, obj)) {
90 diagram_select(dia, obj);
91 } else {
92 diagram_unselect_object(dia, obj);
96 ddisplay_do_update_menu_sensitivity(ddisp);
97 object_add_updates_list(dia->data->selected, dia);
98 diagram_flush(dia);
102 /** Select objects that are directly connected to the currently selected
103 * objects, but only in the active layer.
105 void
106 select_connected_callback(gpointer data, guint action, GtkWidget *widget)
108 Diagram *dia;
109 DDisplay * ddisp = ddisplay_active();
110 GList *objects, *tmp;
112 if (!ddisp) return;
113 dia = ddisp->diagram;
115 objects = dia->data->selected;
117 for (tmp = objects; tmp != NULL; tmp = g_list_next(tmp)) {
118 DiaObject *obj = (DiaObject *)tmp->data;
119 int i;
121 for (i = 0; i < obj->num_handles; i++) {
122 Handle *handle = obj->handles[i];
124 if (handle->connected_to != NULL
125 && dia_object_is_selectable(handle->connected_to->object)
126 && !diagram_is_selected(dia, handle->connected_to->object)) {
127 diagram_select(dia, handle->connected_to->object);
132 for (tmp = objects; tmp != NULL; tmp = tmp->next) {
133 DiaObject *obj = (DiaObject *)tmp->data;
134 int i;
136 for (i = 0; i < obj->num_connections; i++) {
137 ConnectionPoint *connection = obj->connections[i];
138 GList *conns = connection->connected;
140 for (; conns != NULL; conns = g_list_next(conns)) {
141 DiaObject *obj2 = (DiaObject *)conns->data;
143 if (dia_object_is_selectable(obj2)
144 && !diagram_is_selected(dia, obj2)) {
145 diagram_select(dia, obj2);
151 ddisplay_do_update_menu_sensitivity(ddisp);
152 object_add_updates_list(dia->data->selected, dia);
153 diagram_flush(dia);
156 static void
157 select_transitively(Diagram *dia, DiaObject *obj)
159 int i;
160 /* Do breadth-first to avoid overly large stack */
161 GList *newly_selected = NULL;
163 for (i = 0; i < obj->num_handles; i++) {
164 Handle *handle = obj->handles[i];
166 if (handle->connected_to != NULL &&
167 dia_object_is_selectable(handle->connected_to->object)) {
168 DiaObject *connected_object = handle->connected_to->object;
169 if (!diagram_is_selected(dia, connected_object)) {
170 diagram_select(dia, connected_object);
171 newly_selected = g_list_prepend(newly_selected, connected_object);
176 for (i = 0; i < obj->num_connections; i++) {
177 ConnectionPoint *connection = obj->connections[i];
178 GList *conns = connection->connected;
180 for (; conns != NULL; conns = g_list_next(conns)) {
181 DiaObject *obj2 = (DiaObject *)conns->data;
183 if (dia_object_is_selectable(obj2) && !diagram_is_selected(dia, obj2)) {
184 diagram_select(dia, obj2);
185 newly_selected = g_list_prepend(newly_selected, obj2);
190 while (newly_selected != NULL) {
191 select_transitively(dia, (DiaObject *)newly_selected->data);
192 newly_selected = g_list_next(newly_selected);
196 /** Select objects that are in any way connected with a currently selected
197 * object, but only in the active layer.
199 void
200 select_transitive_callback(gpointer data, guint action, GtkWidget *widget)
202 DDisplay *ddisp = ddisplay_active();
203 Diagram *dia;
204 GList *objects, *tmp;
206 if (!ddisp) return;
207 dia = ddisp->diagram;
209 objects = dia->data->selected;
211 for (tmp = objects; tmp != NULL; tmp = g_list_next(tmp)) {
212 select_transitively(dia, (DiaObject *)tmp->data);
215 ddisplay_do_update_menu_sensitivity(ddisp);
216 object_add_updates_list(dia->data->selected, dia);
217 diagram_flush(dia);
220 void
221 select_same_type_callback(gpointer data, guint action, GtkWidget *widget)
223 /* For now, do a brute force version: Check vs. all earlier selected.
224 Later, we should really sort the selecteds first to avoid n^2 */
225 DDisplay *ddisp = ddisplay_active();
226 Diagram *dia;
227 GList *objects, *tmp, *tmp2;
229 if (!ddisp) return;
230 dia = ddisp->diagram;
232 tmp = dia->data->active_layer->objects;
234 objects = dia->data->selected;
236 for (; tmp != NULL; tmp = g_list_next(tmp)) {
237 DiaObject *obj = (DiaObject *)tmp->data;
239 if (!diagram_is_selected(dia, obj)) {
240 for (tmp2 = objects; tmp2 != NULL; tmp2 = g_list_next(tmp2)) {
241 DiaObject *obj2 = (DiaObject *)tmp2->data;
243 if (obj->type == obj2->type) {
244 diagram_select(dia, obj);
245 break;
251 ddisplay_do_update_menu_sensitivity(ddisp);
252 object_add_updates_list(dia->data->selected, dia);
253 diagram_flush(dia);
256 void
257 select_style_callback(gpointer data, guint action, GtkWidget *widget)
259 if (ddisplay_active () == NULL) return;
261 /* simply set the selection style to the value of `action' */
262 selection_style = action;