more leaks plugged and more *_OPTIONAL
[dia.git] / app / properties.c
blob65675a543c3d04c2b18dc5c7e7c9379d5a6986e1
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 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
26 #include "intl.h"
27 #include "properties.h"
28 #include "object_ops.h"
29 #include "connectionpoint_ops.h"
30 #include "undo.h"
31 #include "message.h"
32 #include <string.h>
34 static GtkWidget *dialog = NULL;
35 static GtkWidget *dialog_vbox = NULL;
36 static GtkWidget *object_part = NULL;
37 static Object *current_obj = NULL;
38 static Diagram *current_dia = NULL;
40 static GtkWidget *no_properties_dialog = NULL;
42 static gint properties_respond(GtkWidget *widget,
43 gint response_id,
44 gpointer data);
45 static gboolean properties_key_event(GtkWidget *widget,
46 GdkEventKey *event,
47 gpointer data);
49 static void create_dialog()
51 /* GtkWidget *actionbox; */
52 /* GList *buttons; */
54 dialog = gtk_dialog_new_with_buttons(
55 _("Object properties"),
56 GTK_WINDOW (ddisplay_active()->shell),
57 GTK_DIALOG_DESTROY_WITH_PARENT,
58 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
59 GTK_STOCK_APPLY, GTK_RESPONSE_APPLY,
60 GTK_STOCK_OK, GTK_RESPONSE_OK,
61 NULL);
63 //GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
64 gtk_dialog_set_default_response (GTK_DIALOG(dialog), GTK_RESPONSE_OK);
66 dialog_vbox = GTK_DIALOG(dialog)->vbox;
68 gtk_window_set_role(GTK_WINDOW (dialog), "properties_window");
70 g_signal_connect(G_OBJECT (dialog), "response",
71 G_CALLBACK (properties_respond), NULL);
72 g_signal_connect(G_OBJECT (dialog), "delete_event",
73 G_CALLBACK(gtk_widget_hide), NULL);
74 g_signal_connect(G_OBJECT (dialog), "destroy",
75 G_CALLBACK(gtk_widget_destroyed), &dialog);
76 g_signal_connect(G_OBJECT (dialog), "destroy",
77 G_CALLBACK(gtk_widget_destroyed), &dialog_vbox);
78 g_signal_connect(G_OBJECT (dialog), "key-release-event",
79 G_CALLBACK(properties_key_event), NULL);
81 no_properties_dialog = gtk_label_new(_("This object has no properties."));
82 gtk_widget_show (no_properties_dialog);
83 g_object_ref(G_OBJECT(no_properties_dialog));
84 gtk_object_sink(GTK_OBJECT(no_properties_dialog));
87 static gint
88 properties_part_destroyed(GtkWidget *widget, gpointer data)
90 if (widget == object_part) {
91 object_part = NULL;
92 current_obj = NULL;
93 current_dia = NULL;
95 return 0;
98 static gint
99 properties_dialog_destroyed(GtkWidget *widget, gpointer data)
101 dialog = NULL;
102 return 0;
105 static gboolean
106 properties_key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
108 /* These ought to be done automagically by GtkDialog, but aren't.
109 * Adding them this way makes use of Esc/Enter for other purposes in
110 * the dialog close the dialog -- not good.
113 if (event->keyval == GDK_Escape) {
114 gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_CANCEL);
115 return TRUE;
117 if (event->keyval == GDK_Return) {
118 gtk_dialog_response(GTK_DIALOG(widget), GTK_RESPONSE_OK);
121 return FALSE;
124 static gint
125 properties_respond(GtkWidget *widget,
126 gint response_id,
127 gpointer data)
129 ObjectChange *obj_change = NULL;
131 if ( response_id == GTK_RESPONSE_APPLY
132 || response_id == GTK_RESPONSE_OK) {
133 if ((current_obj != NULL) && (current_dia != NULL)) {
134 object_add_updates(current_obj, current_dia);
135 obj_change = current_obj->ops->apply_properties(current_obj, object_part);
136 object_add_updates(current_obj, current_dia);
138 diagram_update_connections_object(current_dia, current_obj, TRUE);
140 if (obj_change != NULL) {
141 undo_object_change(current_dia, current_obj, obj_change);
144 diagram_modified(current_dia);
146 diagram_object_modified(current_dia, current_obj);
148 diagram_update_extents(current_dia);
150 if (obj_change != NULL) {
151 undo_set_transactionpoint(current_dia->undo);
152 } else {
153 message_warning(_("This object doesn't support Undo/Redo.\n"
154 "Undo information erased."));
155 undo_clear(current_dia->undo);
158 diagram_flush(current_dia);
162 if (response_id != GTK_RESPONSE_APPLY)
163 gtk_widget_hide(widget);
165 return 0;
168 void
169 properties_show(Diagram *dia, Object *obj)
171 GtkWidget *properties = NULL;
173 if (obj != NULL)
174 properties = obj->ops->get_properties(obj, FALSE);
176 if (dialog == NULL)
177 create_dialog();
179 if (obj==NULL) {
180 /* Hide dialog when no object is selected */
181 gtk_widget_hide(dialog);
182 return;
185 if (properties == NULL) { /* No properties or no object */
186 properties = no_properties_dialog;
187 obj = NULL;
188 dia = NULL;
191 if (object_part != NULL) {
192 gtk_container_remove(GTK_CONTAINER(dialog_vbox), object_part);
193 object_part = NULL;
194 current_obj = NULL;
195 current_dia = NULL;
198 if (obj != NULL) {
199 ObjectType *otype;
200 gchar *buf;
202 otype = obj->type;
203 buf = g_strconcat(_("Properties: "), otype->name, NULL);
204 gtk_window_set_title(GTK_WINDOW(dialog), buf);
205 g_free(buf);
206 } else {
207 gtk_window_set_title(GTK_WINDOW(dialog), _("Object properties:"));
210 g_signal_connect (G_OBJECT (properties), "destroy",
211 G_CALLBACK(properties_part_destroyed), NULL);
212 g_signal_connect (G_OBJECT (dialog), "destroy",
213 G_CALLBACK(properties_dialog_destroyed), NULL);
215 gtk_box_pack_start(GTK_BOX(dialog_vbox), properties, TRUE, TRUE, 0);
217 gtk_widget_show (properties);
219 if (obj != current_obj)
220 gtk_window_resize (GTK_WINDOW(dialog), 1, 1); /* resize to minimum */
221 gtk_window_set_transient_for(GTK_WINDOW(dialog),
222 GTK_WINDOW (ddisplay_active()->shell));
223 gtk_window_present (GTK_WINDOW (dialog));
224 object_part = properties;
225 current_obj = obj;
226 current_dia = dia;
229 void
230 properties_hide_if_shown(Diagram *dia, Object *obj)
232 if (current_obj == obj) {
233 properties_show(dia, NULL);
237 void
238 properties_update_if_shown(Diagram *dia, Object *obj)
240 if (current_obj == obj) {
241 properties_show(dia, obj);