/* 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. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "intl.h" #include "properties.h" #include "object_ops.h" #include "connectionpoint_ops.h" #include "undo.h" #include "message.h" #include static GtkWidget *dialog = NULL; static GtkWidget *dialog_vbox = NULL; static GtkWidget *object_part = NULL; static DiaObject *current_obj = NULL; static Diagram *current_dia = NULL; static GtkWidget *no_properties_dialog = NULL; static gint properties_respond(GtkWidget *widget, gint response_id, gpointer data); static gboolean properties_key_event(GtkWidget *widget, GdkEventKey *event, gpointer data); static void create_dialog() { /* GtkWidget *actionbox; */ /* GList *buttons; */ dialog = gtk_dialog_new_with_buttons( _("Object properties"), GTK_WINDOW (ddisplay_active()->shell), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE, GTK_STOCK_APPLY, GTK_RESPONSE_APPLY, GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK); dialog_vbox = GTK_DIALOG(dialog)->vbox; gtk_window_set_role(GTK_WINDOW (dialog), "properties_window"); g_signal_connect(G_OBJECT (dialog), "response", G_CALLBACK (properties_respond), NULL); g_signal_connect(G_OBJECT (dialog), "delete_event", G_CALLBACK(gtk_widget_hide), NULL); g_signal_connect(G_OBJECT (dialog), "destroy", G_CALLBACK(gtk_widget_destroyed), &dialog); g_signal_connect(G_OBJECT (dialog), "destroy", G_CALLBACK(gtk_widget_destroyed), &dialog_vbox); g_signal_connect(G_OBJECT (dialog), "key-release-event", G_CALLBACK(properties_key_event), NULL); no_properties_dialog = gtk_label_new(_("This object has no properties.")); gtk_widget_show (no_properties_dialog); g_object_ref(G_OBJECT(no_properties_dialog)); gtk_object_sink(GTK_OBJECT(no_properties_dialog)); } static gint properties_part_destroyed(GtkWidget *widget, gpointer data) { if (widget == object_part) { object_part = NULL; current_obj = NULL; current_dia = NULL; } return 0; } static gint properties_dialog_destroyed(GtkWidget *widget, gpointer data) { dialog = NULL; return 0; } static gboolean properties_key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) { /* These ought to be done automagically by GtkDialog, but aren't. * Adding them this way makes use of Esc/Enter for other purposes in * the dialog close the dialog -- not good. */ /* if (event->keyval == GDK_Escape) { gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL); return TRUE; } if (event->keyval == GDK_Return) { gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_OK); } */ return FALSE; } static gint properties_respond(GtkWidget *widget, gint response_id, gpointer data) { ObjectChange *obj_change = NULL; if ( response_id == GTK_RESPONSE_APPLY || response_id == GTK_RESPONSE_OK) { if ((current_obj != NULL) && (current_dia != NULL)) { object_add_updates(current_obj, current_dia); obj_change = current_obj->ops->apply_properties(current_obj, object_part); object_add_updates(current_obj, current_dia); diagram_update_connections_object(current_dia, current_obj, TRUE); if (obj_change != NULL) { undo_object_change(current_dia, current_obj, obj_change); } diagram_modified(current_dia); diagram_object_modified(current_dia, current_obj); diagram_update_extents(current_dia); if (obj_change != NULL) { undo_set_transactionpoint(current_dia->undo); } else { message_warning(_("This object doesn't support Undo/Redo.\n" "Undo information erased.")); undo_clear(current_dia->undo); } diagram_flush(current_dia); } } if (response_id != GTK_RESPONSE_APPLY) gtk_widget_hide(widget); return 0; } /** Give focus to the first focusable widget found in `widget'. * @param widget Some (possibly composite) widget. */ static void properties_give_focus(GtkWidget *widget, gpointer data) { if (GTK_WIDGET_CAN_FOCUS(widget)) { gtk_widget_grab_focus(widget); } else { if (GTK_IS_CONTAINER(widget)) { gtk_container_foreach(GTK_CONTAINER(widget), properties_give_focus, data); } } } void properties_show(Diagram *dia, DiaObject *obj) { GtkWidget *properties = NULL; if (obj != NULL) properties = obj->ops->get_properties(obj, FALSE); if (dialog == NULL) create_dialog(); if (obj==NULL) { /* Hide dialog when no object is selected */ gtk_widget_hide(dialog); return; } if (properties == NULL) { /* No properties or no object */ properties = no_properties_dialog; obj = NULL; dia = NULL; } if (object_part != NULL) { gtk_container_remove(GTK_CONTAINER(dialog_vbox), object_part); object_part = NULL; current_obj = NULL; current_dia = NULL; } if (obj != NULL) { DiaObjectType *otype; gchar *buf; otype = obj->type; buf = g_strconcat(_("Properties: "), otype->name, NULL); gtk_window_set_title(GTK_WINDOW(dialog), buf); g_free(buf); } else { gtk_window_set_title(GTK_WINDOW(dialog), _("Object properties:")); } g_signal_connect (G_OBJECT (properties), "destroy", G_CALLBACK(properties_part_destroyed), NULL); g_signal_connect (G_OBJECT (dialog), "destroy", G_CALLBACK(properties_dialog_destroyed), NULL); gtk_box_pack_start(GTK_BOX(dialog_vbox), properties, TRUE, TRUE, 0); gtk_widget_show (properties); properties_give_focus(properties, NULL); if (obj != current_obj) gtk_window_resize (GTK_WINDOW(dialog), 1, 1); /* resize to minimum */ gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW (ddisplay_active()->shell)); gtk_window_present (GTK_WINDOW (dialog)); object_part = properties; current_obj = obj; current_dia = dia; } void properties_hide_if_shown(Diagram *dia, DiaObject *obj) { if (current_obj == obj) { properties_show(dia, NULL); } } void properties_update_if_shown(Diagram *dia, DiaObject *obj) { if (current_obj == obj) { properties_show(dia, obj); } }