2011-10-22 [colin] 3.7.10cvs41
[claws.git] / src / noticeview.c
1 /* 
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 2002-2011 Hiroyuki Yamamoto & The Claws Mail Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  * 
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <time.h>
32
33 #if HAVE_LIBCOMPFACE
34 #  include <compface.h>
35 #endif
36
37 #include "prefs_common.h"
38 #include "gtkutils.h"
39 #include "utils.h"
40 #include "stock_pixmap.h"
41
42 #include "noticeview.h"
43
44 static void noticeview_button_pressed   (GtkButton *button, NoticeView *noticeview);
45 static void noticeview_2ndbutton_pressed(GtkButton *button, NoticeView *noticeview);
46 static gboolean noticeview_icon_pressed (GtkWidget *widget, GdkEventButton *evt,
47                                          NoticeView *noticeview);
48 static gboolean noticeview_visi_notify(GtkWidget *widget,
49                                        GdkEventVisibility *event,
50                                        NoticeView *noticeview);
51 static gboolean noticeview_leave_notify(GtkWidget *widget,
52                                       GdkEventCrossing *event,
53                                       NoticeView *textview);
54 static gboolean noticeview_enter_notify(GtkWidget *widget,
55                                       GdkEventCrossing *event,
56                                       NoticeView *textview);
57
58 static GdkCursor *hand_cursor = NULL;
59
60 NoticeView *noticeview_create(MainWindow *mainwin)
61 {
62         NoticeView *noticeview;
63         GtkWidget  *vbox;
64         GtkWidget  *hsep;
65         GtkWidget  *hbox;
66         GtkWidget  *icon;
67         GtkWidget  *text;
68         GtkWidget  *widget;
69         GtkWidget  *widget2;
70         GtkWidget  *evtbox;
71
72         debug_print("Creating notice view...\n");
73         noticeview = g_new0(NoticeView, 1);
74
75         if (!hand_cursor)
76                 hand_cursor = gdk_cursor_new(GDK_HAND2);
77
78         noticeview->window = mainwin->window;
79         
80         vbox = gtk_vbox_new(FALSE, 4);
81         gtk_widget_show(vbox);
82         hsep = gtk_hseparator_new();
83         gtk_box_pack_start(GTK_BOX(vbox), hsep, FALSE, TRUE, 1);
84         
85         hbox = gtk_hbox_new(FALSE, 4);
86         gtk_widget_show(hbox);
87         gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 1);
88
89         evtbox = gtk_event_box_new();
90         gtk_event_box_set_visible_window(GTK_EVENT_BOX(evtbox), FALSE);
91         gtk_widget_show(evtbox);
92
93         icon = stock_pixmap_widget(noticeview->window, STOCK_PIXMAP_NOTICE_WARN); 
94
95         gtk_widget_show(icon);
96         g_signal_connect(G_OBJECT(evtbox), "button-press-event", 
97                          G_CALLBACK(noticeview_icon_pressed),
98                          (gpointer) noticeview);
99         g_signal_connect(G_OBJECT(evtbox), "motion-notify-event",
100                          G_CALLBACK(noticeview_visi_notify), noticeview);
101         g_signal_connect(G_OBJECT(evtbox), "leave-notify-event",
102                          G_CALLBACK(noticeview_leave_notify), noticeview);
103         g_signal_connect(G_OBJECT(evtbox), "enter-notify-event",
104                          G_CALLBACK(noticeview_enter_notify), noticeview);
105         
106         gtk_container_add(GTK_CONTAINER(evtbox), icon);
107         gtk_box_pack_start(GTK_BOX(hbox), evtbox, FALSE, TRUE, 0);
108         
109         text = gtk_label_new("");
110         gtk_widget_show(text);
111         gtk_box_pack_start(GTK_BOX(hbox), text, FALSE, FALSE, 0);
112
113         widget = gtk_button_new_with_label("");
114         g_signal_connect(G_OBJECT(widget), "clicked", 
115                          G_CALLBACK(noticeview_button_pressed),
116                          (gpointer) noticeview);
117         gtk_box_pack_start(GTK_BOX(hbox), widget, FALSE, FALSE, 4);
118         
119         widget2 = gtk_button_new_with_label("");
120         g_signal_connect(G_OBJECT(widget2), "clicked", 
121                          G_CALLBACK(noticeview_2ndbutton_pressed),
122                          (gpointer) noticeview);
123         gtk_box_pack_start(GTK_BOX(hbox), widget2, FALSE, FALSE, 0);
124         
125         noticeview->vbox   = vbox;
126         noticeview->hsep   = hsep;
127         noticeview->hbox   = hbox;
128         noticeview->icon   = icon;
129         noticeview->text   = text;
130         noticeview->button = widget;
131         noticeview->button2= widget2;
132         noticeview->evtbox = evtbox;
133         noticeview->visible= TRUE;
134 #if !(GTK_CHECK_VERSION(2,12,0))
135         noticeview->tooltips = tips;
136 #endif
137         return noticeview;
138 }
139
140 void noticeview_destroy(NoticeView *noticeview)
141 {
142         g_free(noticeview);
143 }
144
145 gboolean noticeview_is_visible(NoticeView *noticeview)
146 {
147         return noticeview->visible;
148 }
149
150 void noticeview_show(NoticeView *noticeview)
151 {
152         if (!noticeview->visible) {
153                 gtk_widget_show(GTK_WIDGET_PTR(noticeview));
154                 noticeview->visible = TRUE;
155         }       
156 }
157
158 void noticeview_hide(NoticeView *noticeview)
159 {
160         if (noticeview && noticeview->visible) {
161                 gtk_widget_hide(GTK_WIDGET_PTR(noticeview));
162                 noticeview->visible = FALSE;
163         }       
164 }
165
166 void noticeview_set_text(NoticeView *noticeview, const char *text)
167 {
168         cm_return_if_fail(noticeview);
169         gtk_label_set_text(GTK_LABEL(noticeview->text), text);
170 }
171
172 void noticeview_set_button_text(NoticeView *noticeview, const char *text)
173 {
174         cm_return_if_fail(noticeview);
175
176         if (text != NULL) {
177                 gtk_label_set_text
178                         (GTK_LABEL(gtk_bin_get_child(GTK_BIN((noticeview->button)))), text);
179                 gtk_widget_show(noticeview->button);
180         } else
181                 gtk_widget_hide(noticeview->button);
182         
183         /* Callers defining only one button don't have to mind 
184          * resetting the second one. Callers defining two have
185          * to define the second button after the first one. 
186          */
187         gtk_widget_hide(noticeview->button2);
188 }
189
190 void noticeview_set_button_press_callback(NoticeView    *noticeview,
191                                           void          (*callback)(void),
192                                           gpointer      *user_data)
193 {
194         noticeview->press     = (void (*) (NoticeView *, gpointer)) callback;
195         noticeview->user_data = user_data;
196 }
197
198 static void noticeview_button_pressed(GtkButton *button, NoticeView *noticeview)
199 {
200         if (noticeview->press) {
201                 noticeview->press(noticeview, noticeview->user_data);
202         }
203 }
204
205 static gboolean noticeview_icon_pressed(GtkWidget *widget, GdkEventButton *evt,
206                                     NoticeView *noticeview)
207 {
208         if (evt && evt->button == 1 && noticeview->icon_clickable) {
209                 noticeview_button_pressed(NULL, noticeview);
210         }
211         return FALSE;
212 }
213
214 static gboolean noticeview_visi_notify(GtkWidget *widget,
215                                        GdkEventVisibility *event,
216                                        NoticeView *noticeview)
217 {
218         if (noticeview->icon_clickable)
219                 gdk_window_set_cursor(gtk_widget_get_window(noticeview->evtbox), hand_cursor);
220         return FALSE;
221 }
222
223 static gboolean noticeview_leave_notify(GtkWidget *widget,
224                                       GdkEventCrossing *event,
225                                       NoticeView *noticeview)
226 {
227         gdk_window_set_cursor(gtk_widget_get_window(noticeview->evtbox), NULL);
228         return FALSE;
229 }
230
231 static gboolean noticeview_enter_notify(GtkWidget *widget,
232                                       GdkEventCrossing *event,
233                                       NoticeView *noticeview)
234 {
235         if (noticeview->icon_clickable)
236                 gdk_window_set_cursor(gtk_widget_get_window(noticeview->evtbox), hand_cursor);
237         return FALSE;
238 }
239
240 void noticeview_set_2ndbutton_text(NoticeView *noticeview, const char *text)
241 {
242         cm_return_if_fail(noticeview);
243
244         if (text != NULL) {
245                 gtk_label_set_text
246                         (GTK_LABEL(gtk_bin_get_child(GTK_BIN((noticeview->button2)))), text);
247                 gtk_widget_show(noticeview->button2);
248         } else
249                 gtk_widget_hide(noticeview->button2);
250 }
251
252 void noticeview_set_2ndbutton_press_callback(NoticeView *noticeview,
253                                           void          (*callback)(void),
254                                           gpointer      *user_data)
255 {
256         noticeview->press2     = (void (*) (NoticeView *, gpointer)) callback;
257         noticeview->user_data2 = user_data;
258 }
259
260 static void noticeview_2ndbutton_pressed(GtkButton *button, NoticeView *noticeview)
261 {
262         if (noticeview->press2) {
263                 noticeview->press2(noticeview, noticeview->user_data2);
264         }
265 }
266
267 void noticeview_set_icon(NoticeView *noticeview, StockPixmap icon)
268 {
269         GdkPixbuf *pixbuf;
270         
271         if (stock_pixbuf_gdk(noticeview->window, icon, &pixbuf) < 0)
272                 return;
273         
274         gtk_image_set_from_pixbuf(GTK_IMAGE(noticeview->icon), pixbuf);
275 }
276
277 void noticeview_set_icon_clickable(NoticeView *noticeview, gboolean setting)
278 {
279         noticeview->icon_clickable = setting;
280 }               
281
282 void noticeview_set_tooltip (NoticeView *noticeview, const gchar *text)
283 {
284 #if !(GTK_CHECK_VERSION(2,12,0))
285         GtkTooltips *tips = noticeview->tooltips;
286 #endif
287         CLAWS_SET_TIP(noticeview->evtbox,
288                         text);
289
290 }