/* Dia -- an diagram creation/manipulation program * Copyright (C) 1998 Alexander Larsson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* select.c -- callbacks to implement the Select menu */ #include #include #include "select.h" #include "menus.h" #include "intl.h" #include "object_ops.h" enum SelectionStyle selection_style = SELECT_REPLACE; void select_all_callback(gpointer data, guint action, GtkWidget *widget) { Diagram *dia; GList *objects; DDisplay * ddisp = ddisplay_active(); if (!ddisp) return; dia = ddisp->diagram; objects = dia->data->active_layer->objects; while (objects != NULL) { DiaObject *obj = (DiaObject *)objects->data; if (!diagram_is_selected(dia, obj)) { diagram_select(dia, obj); } objects = g_list_next(objects); } ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } void select_none_callback(gpointer data, guint action, GtkWidget *widget) { Diagram * dia; DDisplay * ddisp = ddisplay_active(); if (!ddisp) return; dia = ddisp->diagram; diagram_remove_all_selected(dia, TRUE); ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } void select_invert_callback(gpointer data, guint action, GtkWidget *widget) { Diagram *dia; GList *tmp; DDisplay * ddisp = ddisplay_active(); if (!ddisp) return; dia = ddisp->diagram; tmp = dia->data->active_layer->objects; for (; tmp != NULL; tmp = g_list_next(tmp)) { DiaObject *obj = (DiaObject *)tmp->data; if (!diagram_is_selected(dia, obj)) { diagram_select(dia, obj); } else { diagram_unselect_object(dia, obj); } } ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } /** Select objects that are directly connected to the currently selected * objects, but only in the active layer. */ void select_connected_callback(gpointer data, guint action, GtkWidget *widget) { Diagram *dia; DDisplay * ddisp = ddisplay_active(); GList *objects, *tmp; if (!ddisp) return; dia = ddisp->diagram; objects = dia->data->selected; for (tmp = objects; tmp != NULL; tmp = g_list_next(tmp)) { DiaObject *obj = (DiaObject *)tmp->data; int i; for (i = 0; i < obj->num_handles; i++) { Handle *handle = obj->handles[i]; if (handle->connected_to != NULL && dia_object_is_selectable(handle->connected_to->object) && !diagram_is_selected(dia, handle->connected_to->object)) { diagram_select(dia, handle->connected_to->object); } } } for (tmp = objects; tmp != NULL; tmp = tmp->next) { DiaObject *obj = (DiaObject *)tmp->data; int i; for (i = 0; i < obj->num_connections; i++) { ConnectionPoint *connection = obj->connections[i]; GList *conns = connection->connected; for (; conns != NULL; conns = g_list_next(conns)) { DiaObject *obj2 = (DiaObject *)conns->data; if (dia_object_is_selectable(obj2) && !diagram_is_selected(dia, obj2)) { diagram_select(dia, obj2); } } } } ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } static void select_transitively(Diagram *dia, DiaObject *obj) { int i; /* Do breadth-first to avoid overly large stack */ GList *newly_selected = NULL; for (i = 0; i < obj->num_handles; i++) { Handle *handle = obj->handles[i]; if (handle->connected_to != NULL && dia_object_is_selectable(handle->connected_to->object)) { DiaObject *connected_object = handle->connected_to->object; if (!diagram_is_selected(dia, connected_object)) { diagram_select(dia, connected_object); newly_selected = g_list_prepend(newly_selected, connected_object); } } } for (i = 0; i < obj->num_connections; i++) { ConnectionPoint *connection = obj->connections[i]; GList *conns = connection->connected; for (; conns != NULL; conns = g_list_next(conns)) { DiaObject *obj2 = (DiaObject *)conns->data; if (dia_object_is_selectable(obj2) && !diagram_is_selected(dia, obj2)) { diagram_select(dia, obj2); newly_selected = g_list_prepend(newly_selected, obj2); } } } while (newly_selected != NULL) { select_transitively(dia, (DiaObject *)newly_selected->data); newly_selected = g_list_next(newly_selected); } } /** Select objects that are in any way connected with a currently selected * object, but only in the active layer. */ void select_transitive_callback(gpointer data, guint action, GtkWidget *widget) { DDisplay *ddisp = ddisplay_active(); Diagram *dia; GList *objects, *tmp; if (!ddisp) return; dia = ddisp->diagram; objects = dia->data->selected; for (tmp = objects; tmp != NULL; tmp = g_list_next(tmp)) { select_transitively(dia, (DiaObject *)tmp->data); } ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } void select_same_type_callback(gpointer data, guint action, GtkWidget *widget) { /* For now, do a brute force version: Check vs. all earlier selected. Later, we should really sort the selecteds first to avoid n^2 */ DDisplay *ddisp = ddisplay_active(); Diagram *dia; GList *objects, *tmp, *tmp2; if (!ddisp) return; dia = ddisp->diagram; tmp = dia->data->active_layer->objects; objects = dia->data->selected; for (; tmp != NULL; tmp = g_list_next(tmp)) { DiaObject *obj = (DiaObject *)tmp->data; if (!diagram_is_selected(dia, obj)) { for (tmp2 = objects; tmp2 != NULL; tmp2 = g_list_next(tmp2)) { DiaObject *obj2 = (DiaObject *)tmp2->data; if (obj->type == obj2->type) { diagram_select(dia, obj); break; } } } } ddisplay_do_update_menu_sensitivity(ddisp); object_add_updates_list(dia->data->selected, dia); diagram_flush(dia); } void select_style_callback(gpointer data, guint action, GtkWidget *widget) { if (ddisplay_active () == NULL) return; /* simply set the selection style to the value of `action' */ selection_style = action; }