1 /*
2 * Copyright 2008 Department of Mathematical Sciences, New Mexico State University
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * DEPARTMENT OF MATHEMATICAL SCIENCES OR NEW MEXICO STATE UNIVERSITY BE
18 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
19 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 */
22
23 #include "gbdfed.h"
24
25 /*
26 * The shared error dialog and the label for the message.
27 */
28 static GtkWidget *errd;
29 static GtkWidget *errmsg;
30
31 /*
32 * The shared question dialog, the label for the question, and the
33 * value representing the answer.
34 */
35 static GtkWidget *questd;
36 static GtkWidget *question;
37 static GtkWidget *yes;
38 static GtkWidget *no;
39
40 void
guiutil_show_dialog_centered(GtkWidget * dialog,GtkWidget * parent)41 guiutil_show_dialog_centered(GtkWidget *dialog, GtkWidget *parent)
42 {
43 if (GTK_WINDOW(parent) != gtk_window_get_transient_for(GTK_WINDOW(dialog)))
44 gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent));
45 gtk_widget_show(dialog);
46 }
47
48 void
guiutil_error_message(GtkWidget * parent,gchar * text)49 guiutil_error_message(GtkWidget *parent, gchar *text)
50 {
51 GtkWidget *ok, *hbox, *image;
52 GtkStockItem item;
53
54 if (errd == 0) {
55 errd = gtk_dialog_new();
56 (void) g_signal_connect(G_OBJECT(errd), "delete_event",
57 G_CALLBACK(gtk_widget_hide), 0);
58
59 hbox = gtk_hbox_new(FALSE, 0);
60
61 /*
62 * Create the error icon.
63 */
64 if (gtk_stock_lookup(GTK_STOCK_DIALOG_ERROR, &item)) {
65 /*
66 * Set the dialog title.
67 */
68 gtk_window_set_title(GTK_WINDOW(errd), item.label);
69 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_ERROR,
70 GTK_ICON_SIZE_DIALOG);
71 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 2);
72 } else {
73 /*
74 * Probably not necessary, but use some default icon here.
75 */
76 }
77
78 errmsg = gtk_label_new(text);
79 gtk_box_pack_start(GTK_BOX(hbox), errmsg, TRUE, TRUE, 2);
80 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(errd)->vbox), hbox);
81
82 ok = gtk_dialog_add_button(GTK_DIALOG(errd), GTK_STOCK_CLOSE,
83 GTK_RESPONSE_CLOSE);
84 (void) g_signal_connect_object(G_OBJECT(ok), "clicked",
85 G_CALLBACK(gtk_widget_hide),
86 (gpointer) errd,
87 G_CONNECT_SWAPPED);
88
89 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(errd)->action_area), ok);
90
91 gtk_widget_show_all(errd);
92
93 gtk_window_set_modal(GTK_WINDOW(errd), TRUE);
94 } else
95 gtk_label_set_text(GTK_LABEL(errmsg), text);
96
97 /*
98 * Center the dialog and display it.
99 */
100 guiutil_show_dialog_centered(errd, parent);
101
102 /*
103 * Ring the bell.
104 */
105 gdk_beep();
106 }
107
108 gboolean
guiutil_yes_or_no(GtkWidget * parent,gchar * text,gboolean default_answer)109 guiutil_yes_or_no(GtkWidget *parent, gchar *text, gboolean default_answer)
110 {
111 GtkWidget *hbox, *image;
112 GList *kids;
113 gint ans;
114 GtkStockItem item;
115
116 if (questd == 0) {
117 questd = gtk_dialog_new();
118 gtk_window_set_resizable(GTK_WINDOW(questd), TRUE);
119
120 (void) g_signal_connect(G_OBJECT(questd), "delete_event",
121 G_CALLBACK(gtk_widget_hide), 0);
122
123 hbox = gtk_hbox_new(FALSE, 0);
124
125 /*
126 * Create the question icon.
127 */
128 if (gtk_stock_lookup(GTK_STOCK_DIALOG_QUESTION, &item)) {
129 /*
130 * Set the dialog title.
131 */
132 gtk_window_set_title(GTK_WINDOW(questd), item.label);
133 image = gtk_image_new_from_stock(GTK_STOCK_DIALOG_QUESTION,
134 GTK_ICON_SIZE_DIALOG);
135 gtk_box_pack_start(GTK_BOX(hbox), image, FALSE, FALSE, 2);
136 } else {
137 /*
138 * Probably not necessary, but use some default icon here.
139 */
140 }
141
142 question = gtk_label_new(text);
143
144 gtk_box_pack_start(GTK_BOX(hbox), question, TRUE, TRUE, 2);
145 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(questd)->vbox), hbox);
146
147 /*
148 * Make sure the buttons are evenly distributed in the button box.
149 */
150 gtk_button_box_set_layout(GTK_BUTTON_BOX(GTK_DIALOG(questd)->action_area), GTK_BUTTONBOX_SPREAD);
151
152 gtk_dialog_add_buttons(GTK_DIALOG(questd),
153 GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
154 GTK_STOCK_NO, GTK_RESPONSE_CANCEL, NULL);
155
156 /*
157 * Get the two children buttons out now so focus can be set on either
158 * when needed.
159 */
160 kids = gtk_container_get_children(GTK_CONTAINER(GTK_DIALOG(questd)->action_area));
161 no = GTK_WIDGET(g_list_nth_data(kids, 0));
162 yes = GTK_WIDGET(g_list_nth_data(kids, 1));
163 g_list_free(kids);
164
165 gtk_widget_show_all(questd);
166
167 gtk_window_set_modal(GTK_WINDOW(questd), TRUE);
168 } else
169 gtk_label_set_text(GTK_LABEL(question), text);
170
171 /*
172 * Force the dialog to reset to its minimum size.
173 */
174 if (questd->window != NULL)
175 gtk_window_resize(GTK_WINDOW(questd), 1, 1);
176
177 /*
178 * Center the dialog and display it.
179 */
180 guiutil_show_dialog_centered(questd, parent);
181
182 /*
183 * Force the default answer button to have the focus.
184 */
185 if (default_answer)
186 gtk_widget_grab_focus(yes);
187 else
188 gtk_widget_grab_focus(no);
189
190 ans = gtk_dialog_run(GTK_DIALOG(questd));
191
192 gtk_widget_hide(questd);
193
194 return (ans == GTK_RESPONSE_ACCEPT) ? TRUE : FALSE;
195 }
196
197 void
guiutil_util_set_tooltip(GtkWidget * w,gchar * text)198 guiutil_util_set_tooltip(GtkWidget *w, gchar *text)
199 {
200 #if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 12
201 gtk_widget_set_tooltip_text(w, text);
202 #else
203 GtkTooltips *tt;
204
205 tt = gtk_tooltips_new();
206 gtk_tooltips_set_tip(tt, w, text, 0);
207 #endif
208 }
209
210 static GdkCursor *watch_cursor;
211
212 void
guiutil_busy_cursor(GtkWidget * w,gboolean on)213 guiutil_busy_cursor(GtkWidget *w, gboolean on)
214 {
215 if (watch_cursor == 0)
216 watch_cursor = gdk_cursor_new(GDK_WATCH);
217
218 if (on)
219 gdk_window_set_cursor(w->window, watch_cursor);
220 else
221 gdk_window_set_cursor(w->window, 0);
222 }
223
224 void
guiutil_cursor_cleanup()225 guiutil_cursor_cleanup()
226 {
227 if (watch_cursor != 0)
228 gdk_cursor_unref(watch_cursor);
229 watch_cursor = 0;
230 }
231