]> www.fi.muni.cz Git - evince.git/blob - cut-n-paste/gedit-message-area/gedit-message-area.c
Use GTK_RESPONSE_CLOSE instead of GTK_RESPONSE_CANCEL for the close
[evince.git] / cut-n-paste / gedit-message-area / gedit-message-area.c
1 /*
2  * gedit-message-area.c
3  * This file is part of gedit
4  *
5  * Copyright (C) 2005 - Paolo Maggi
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 /*
24  * Modified by the gedit Team, 2005. See the AUTHORS file for a
25  * list of people on the gedit Team.
26  * See the ChangeLog files for a list of changes.
27  *
28  * $Id: gedit-message-area.c 5887 2007-09-07 07:20:19Z pborelli $
29  */
30
31 /* TODO: Style properties */
32
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36
37 #include <glib/gi18n.h>
38 #include <gtk/gtk.h>
39 #include <gdk/gdk.h>
40 #include <gdk/gdkkeysyms.h>
41
42 #include "gedit-message-area.h"
43
44 #define GEDIT_MESSAGE_AREA_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), \
45                                                GEDIT_TYPE_MESSAGE_AREA, \
46                                                GeditMessageAreaPrivate))
47
48 struct _GeditMessageAreaPrivate
49 {
50         GtkWidget *main_hbox;
51
52         GtkWidget *contents;
53         GtkWidget *action_area;
54
55         gboolean changing_style;
56 };
57
58 typedef struct _ResponseData ResponseData;
59
60 struct _ResponseData
61 {
62         gint response_id;
63 };
64
65 enum {
66         RESPONSE,
67         CLOSE,
68         LAST_SIGNAL
69 };
70
71 static guint signals[LAST_SIGNAL];
72
73 G_DEFINE_TYPE(GeditMessageArea, gedit_message_area, GTK_TYPE_HBOX)
74
75
76 static void
77 gedit_message_area_finalize (GObject *object)
78 {
79         /*
80         GeditMessageArea *message_area = GEDIT_MESSAGE_AREA (object);
81         */
82
83         G_OBJECT_CLASS (gedit_message_area_parent_class)->finalize (object);
84 }
85
86 static ResponseData *
87 get_response_data (GtkWidget *widget,
88                    gboolean   create)
89 {
90         ResponseData *ad = g_object_get_data (G_OBJECT (widget),
91                                               "gedit-message-area-response-data");
92
93         if (ad == NULL && create)
94         {
95                 ad = g_new (ResponseData, 1);
96
97                 g_object_set_data_full (G_OBJECT (widget),
98                                         "gedit-message-area-response-data",
99                                         ad,
100                                         g_free);
101         }
102
103         return ad;
104 }
105
106 static GtkWidget *
107 find_button (GeditMessageArea *message_area,
108              gint              response_id)
109 {
110         GList *children, *tmp_list;
111         GtkWidget *child = NULL;
112
113         children = gtk_container_get_children (
114                         GTK_CONTAINER (message_area->priv->action_area));
115
116         for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
117         {
118                 ResponseData *rd = get_response_data (tmp_list->data, FALSE);
119
120                 if (rd && rd->response_id == response_id)
121                 {
122                         child = tmp_list->data;
123                         break;
124                 }
125         }
126
127         g_list_free (children);
128
129         return child;
130 }
131
132 static void
133 gedit_message_area_close (GeditMessageArea *message_area)
134 {
135         if (!find_button (message_area, GTK_RESPONSE_CLOSE))
136                 return;
137
138         /* emit response signal */
139         gedit_message_area_response (GEDIT_MESSAGE_AREA (message_area),
140                                      GTK_RESPONSE_CLOSE);
141 }
142
143 static gboolean
144 paint_message_area (GtkWidget      *widget,
145                     GdkEventExpose *event,
146                     gpointer        user_data)
147 {
148         gtk_paint_flat_box (widget->style,
149                             widget->window,
150                             GTK_STATE_NORMAL,
151                             GTK_SHADOW_OUT,
152                             NULL,
153                             widget,
154                             "tooltip",
155                             widget->allocation.x + 1,
156                             widget->allocation.y + 1,
157                             widget->allocation.width - 2,
158                             widget->allocation.height - 2);
159
160         return FALSE;
161 }
162
163 static void
164 gedit_message_area_class_init (GeditMessageAreaClass *klass)
165 {
166         GObjectClass *object_class;
167         GtkBindingSet *binding_set;
168
169         object_class = G_OBJECT_CLASS (klass);
170         object_class->finalize = gedit_message_area_finalize;
171
172         klass->close = gedit_message_area_close;
173
174         g_type_class_add_private (object_class, sizeof(GeditMessageAreaPrivate));
175
176         signals[RESPONSE] = g_signal_new ("response",
177                                           G_OBJECT_CLASS_TYPE (klass),
178                                           G_SIGNAL_RUN_LAST,
179                                           G_STRUCT_OFFSET (GeditMessageAreaClass, response),
180                                           NULL, NULL,
181                                           g_cclosure_marshal_VOID__INT,
182                                           G_TYPE_NONE, 1,
183                                           G_TYPE_INT);
184
185         signals[CLOSE] =  g_signal_new ("close",
186                                         G_OBJECT_CLASS_TYPE (klass),
187                                         G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
188                                         G_STRUCT_OFFSET (GeditMessageAreaClass, close),
189                                         NULL, NULL,
190                                         g_cclosure_marshal_VOID__VOID,
191                                         G_TYPE_NONE, 0);
192
193         binding_set = gtk_binding_set_by_class (klass);
194
195         gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "close", 0);
196 }
197
198 static void
199 style_set (GtkWidget        *widget,
200            GtkStyle         *prev_style,
201            GeditMessageArea *message_area)
202 {
203         GtkWidget *window;
204         GtkStyle *style;
205
206         if (message_area->priv->changing_style)
207                 return;
208
209         /* This is a hack needed to use the tooltip background color */
210         window = gtk_window_new (GTK_WINDOW_POPUP);
211         gtk_widget_set_name (window, "gtk-tooltip");
212         gtk_widget_ensure_style (window);
213         style = gtk_widget_get_style (window);
214
215         message_area->priv->changing_style = TRUE;
216         gtk_widget_set_style (GTK_WIDGET (message_area), style);
217         message_area->priv->changing_style = FALSE;
218
219         gtk_widget_destroy (window);
220
221         gtk_widget_queue_draw (GTK_WIDGET (message_area));
222 }
223
224 static void
225 gedit_message_area_init (GeditMessageArea *message_area)
226 {
227         message_area->priv = GEDIT_MESSAGE_AREA_GET_PRIVATE (message_area);
228
229         message_area->priv->main_hbox = gtk_hbox_new (FALSE, 16); /* FIXME: use style properties */
230         gtk_widget_show (message_area->priv->main_hbox);
231         gtk_container_set_border_width (GTK_CONTAINER (message_area->priv->main_hbox),
232                                         8); /* FIXME: use style properties */
233
234         message_area->priv->action_area = gtk_vbox_new (TRUE, 10); /* FIXME: use style properties */
235         gtk_widget_show (message_area->priv->action_area);
236         gtk_box_pack_end (GTK_BOX (message_area->priv->main_hbox),
237                             message_area->priv->action_area,
238                             FALSE,
239                             TRUE,
240                             0);
241
242         gtk_box_pack_start (GTK_BOX (message_area),
243                             message_area->priv->main_hbox,
244                             TRUE,
245                             TRUE,
246                             0);
247
248         gtk_widget_set_app_paintable (GTK_WIDGET (message_area), TRUE);
249
250         g_signal_connect (message_area,
251                           "expose-event",
252                           G_CALLBACK (paint_message_area),
253                           NULL);
254
255         /* Note that we connect to style-set on one of the internal
256          * widgets, not on the message area itself, since gtk does
257          * not deliver any further style-set signals for a widget on
258          * which the style has been forced with gtk_widget_set_style() */
259         g_signal_connect (message_area->priv->main_hbox,
260                           "style-set",
261                           G_CALLBACK (style_set),
262                           message_area);
263 }
264
265 static gint
266 get_response_for_widget (GeditMessageArea *message_area,
267                          GtkWidget        *widget)
268 {
269         ResponseData *rd;
270
271         rd = get_response_data (widget, FALSE);
272         if (!rd)
273                 return GTK_RESPONSE_NONE;
274         else
275                 return rd->response_id;
276 }
277
278 static void
279 action_widget_activated (GtkWidget *widget, GeditMessageArea *message_area)
280 {
281         gint response_id;
282
283         response_id = get_response_for_widget (message_area, widget);
284
285         gedit_message_area_response (message_area, response_id);
286 }
287
288 void
289 gedit_message_area_add_action_widget (GeditMessageArea *message_area,
290                                       GtkWidget        *child,
291                                       gint              response_id)
292 {
293         ResponseData *ad;
294         guint signal_id;
295
296         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
297         g_return_if_fail (GTK_IS_WIDGET (child));
298
299         ad = get_response_data (child, TRUE);
300
301         ad->response_id = response_id;
302
303         if (GTK_IS_BUTTON (child))
304                 signal_id = g_signal_lookup ("clicked", GTK_TYPE_BUTTON);
305         else
306                 signal_id = GTK_WIDGET_GET_CLASS (child)->activate_signal;
307
308         if (signal_id)
309         {
310                 GClosure *closure;
311
312                 closure = g_cclosure_new_object (G_CALLBACK (action_widget_activated),
313                                                  G_OBJECT (message_area));
314
315                 g_signal_connect_closure_by_id (child,
316                                                 signal_id,
317                                                 0,
318                                                 closure,
319                                                 FALSE);
320         }
321         else
322                 g_warning ("Only 'activatable' widgets can be packed into the action area of a GeditMessageArea");
323
324         if (response_id != GTK_RESPONSE_HELP)
325                 gtk_box_pack_start (GTK_BOX (message_area->priv->action_area),
326                                     child,
327                                     FALSE,
328                                     FALSE,
329                                     0);
330         else
331                 gtk_box_pack_end (GTK_BOX (message_area->priv->action_area),
332                                     child,
333                                     FALSE,
334                                     FALSE,
335                                     0);
336 }
337
338 void
339 gedit_message_area_set_contents (GeditMessageArea *message_area,
340                                  GtkWidget        *contents)
341 {
342         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
343         g_return_if_fail (GTK_IS_WIDGET (contents));
344
345         message_area->priv->contents = contents;
346         gtk_box_pack_start (GTK_BOX (message_area->priv->main_hbox),
347                             message_area->priv->contents,
348                             TRUE,
349                             TRUE,
350                             0);
351 }
352
353 GtkWidget *
354 gedit_message_area_get_contents (GeditMessageArea *message_area)
355 {
356         return message_area->priv->contents;
357 }
358
359 GtkWidget*
360 gedit_message_area_add_button (GeditMessageArea *message_area,
361                                const gchar      *button_text,
362                                gint              response_id)
363 {
364         GtkWidget *button;
365
366         g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL);
367         g_return_val_if_fail (button_text != NULL, NULL);
368
369         button = gtk_button_new_from_stock (button_text);
370
371         GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
372
373         gtk_widget_show (button);
374
375         gedit_message_area_add_action_widget (message_area,
376                                               button,
377                                               response_id);
378
379         return button;
380 }
381
382 void
383 gedit_message_area_add_buttons_valist (GeditMessageArea *message_area,
384                                        const gchar      *first_button_text,
385                                        va_list           args)
386 {
387         const gchar* text;
388         gint response_id;
389
390         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
391
392         if (first_button_text == NULL)
393                 return;
394
395         text = first_button_text;
396         response_id = va_arg (args, gint);
397
398         while (text != NULL)
399         {
400                 gedit_message_area_add_button (message_area,
401                                                text,
402                                                response_id);
403
404                 text = va_arg (args, gchar*);
405                 if (text == NULL)
406                         break;
407
408                 response_id = va_arg (args, int);
409         }
410 }
411
412 void
413 gedit_message_area_add_buttons (GeditMessageArea *message_area,
414                                 const gchar      *first_button_text,
415                                 ...)
416 {
417         va_list args;
418
419         va_start (args, first_button_text);
420
421         gedit_message_area_add_buttons_valist (message_area,
422                                                first_button_text,
423                                                args);
424
425         va_end (args);
426 }
427
428 GtkWidget *
429 gedit_message_area_new (void)
430 {
431         return g_object_new (GEDIT_TYPE_MESSAGE_AREA, NULL);
432 }
433
434 GtkWidget *
435 gedit_message_area_new_with_buttons (const gchar *first_button_text,
436                                      ...)
437 {
438         GeditMessageArea *message_area;
439         va_list args;
440
441         message_area = GEDIT_MESSAGE_AREA (gedit_message_area_new ());
442
443         va_start (args, first_button_text);
444
445         gedit_message_area_add_buttons_valist (message_area,
446                                                first_button_text,
447                                                args);
448
449         va_end (args);
450
451         return GTK_WIDGET (message_area);
452 }
453
454 void
455 gedit_message_area_set_response_sensitive (GeditMessageArea *message_area,
456                                            gint              response_id,
457                                            gboolean          setting)
458 {
459         GList *children;
460         GList *tmp_list;
461
462         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
463
464         children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area));
465
466         tmp_list = children;
467         while (tmp_list != NULL)
468         {
469                 GtkWidget *widget = tmp_list->data;
470                 ResponseData *rd = get_response_data (widget, FALSE);
471
472                 if (rd && rd->response_id == response_id)
473                         gtk_widget_set_sensitive (widget, setting);
474
475                 tmp_list = g_list_next (tmp_list);
476         }
477
478         g_list_free (children);
479 }
480
481 void
482 gedit_message_area_set_default_response (GeditMessageArea *message_area,
483                                          gint              response_id)
484 {
485         GList *children;
486         GList *tmp_list;
487
488         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
489
490         children = gtk_container_get_children (GTK_CONTAINER (message_area->priv->action_area));
491
492         tmp_list = children;
493         while (tmp_list != NULL)
494         {
495                 GtkWidget *widget = tmp_list->data;
496                 ResponseData *rd = get_response_data (widget, FALSE);
497
498                 if (rd && rd->response_id == response_id)
499                 gtk_widget_grab_default (widget);
500
501                 tmp_list = g_list_next (tmp_list);
502         }
503
504         g_list_free (children);
505 }
506
507 void
508 gedit_message_area_response (GeditMessageArea *message_area,
509                              gint              response_id)
510 {
511         g_return_if_fail (GEDIT_IS_MESSAGE_AREA (message_area));
512
513         g_signal_emit (message_area,
514                        signals[RESPONSE],
515                        0,
516                        response_id);
517 }
518
519 GtkWidget *
520 gedit_message_area_add_stock_button_with_text (GeditMessageArea *message_area,
521                                                const gchar      *text,
522                                                const gchar      *stock_id,
523                                                gint              response_id)
524 {
525         GtkWidget *button;
526
527         g_return_val_if_fail (GEDIT_IS_MESSAGE_AREA (message_area), NULL);
528         g_return_val_if_fail (text != NULL, NULL);
529         g_return_val_if_fail (stock_id != NULL, NULL);
530
531         button = gtk_button_new_with_mnemonic (text);
532         gtk_button_set_image (GTK_BUTTON (button),
533                               gtk_image_new_from_stock (stock_id,
534                                                         GTK_ICON_SIZE_BUTTON));
535
536         GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
537
538         gtk_widget_show (button);
539
540         gedit_message_area_add_action_widget (message_area,
541                                               button,
542                                               response_id);
543
544         return button;
545 }
546