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
);
50 objects
= g_list_next(objects
);
53 ddisplay_do_update_menu_sensitivity(ddisp
);
54 object_add_updates_list(dia
->data
->selected
, dia
);
59 select_none_callback(gpointer data
, guint action
, GtkWidget
*widget
)
62 DDisplay
* ddisp
= ddisplay_active();
67 diagram_remove_all_selected(dia
, TRUE
);
69 ddisplay_do_update_menu_sensitivity(ddisp
);
70 object_add_updates_list(dia
->data
->selected
, dia
);
75 select_invert_callback(gpointer data
, guint action
, GtkWidget
*widget
)
79 DDisplay
* ddisp
= ddisplay_active();
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
);
92 diagram_unselect_object(dia
, obj
);
96 ddisplay_do_update_menu_sensitivity(ddisp
);
97 object_add_updates_list(dia
->data
->selected
, dia
);
102 /** Select objects that are directly connected to the currently selected
103 * objects, but only in the active layer.
106 select_connected_callback(gpointer data
, guint action
, GtkWidget
*widget
)
109 DDisplay
* ddisp
= ddisplay_active();
110 GList
*objects
, *tmp
;
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
;
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
;
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
);
157 select_transitively(Diagram
*dia
, DiaObject
*obj
)
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.
200 select_transitive_callback(gpointer data
, guint action
, GtkWidget
*widget
)
202 DDisplay
*ddisp
= ddisplay_active();
204 GList
*objects
, *tmp
;
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
);
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();
227 GList
*objects
, *tmp
, *tmp2
;
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
);
251 ddisplay_do_update_menu_sensitivity(ddisp
);
252 object_add_updates_list(dia
->data
->selected
, dia
);
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
;