* rename gtk2 => gtk
[modest] / src / gtk / modest-edit-msg-window.c
1 /* Copyright (c) 2006, Nokia Corporation
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  *   notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  *   notice, this list of conditions and the following disclaimer in the
12  *   documentation and/or other materials provided with the distribution.
13  * * Neither the name of the Nokia Corporation nor the names of its
14  *   contributors may be used to endorse or promote products derived from
15  *   this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
18  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include "modest-edit-msg-window.h"
31 #include <widgets/modest-msg-view.h>
32 #include <modest-widget-memory.h>
33 #include <modest-widget-factory.h>
34 #include "modest-icon-names.h"
35
36 static void  modest_edit_msg_window_class_init   (ModestEditMsgWindowClass *klass);
37 static void  modest_edit_msg_window_init         (ModestEditMsgWindow *obj);
38 static void  modest_edit_msg_window_finalize     (GObject *obj);
39
40 /* list my signals */
41 enum {
42         /* MY_SIGNAL_1, */
43         /* MY_SIGNAL_2, */
44         LAST_SIGNAL
45 };
46
47 typedef struct _ModestEditMsgWindowPrivate ModestEditMsgWindowPrivate;
48 struct _ModestEditMsgWindowPrivate {
49
50         ModestConf *conf;
51         ModestWidgetFactory *factory;
52         
53         GtkWidget      *toolbar, *menubar;
54         GtkWidget      *msg_body;
55         GtkWidget      *to_field, *cc_field, *bcc_field,
56                        *subject_field;
57 };
58 #define MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(o)      (G_TYPE_INSTANCE_GET_PRIVATE((o), \
59                                                     MODEST_TYPE_EDIT_MSG_WINDOW, \
60                                                     ModestEditMsgWindowPrivate))
61 /* globals */
62 static GtkWindowClass *parent_class = NULL;
63
64 /* uncomment the following if you have defined any signals */
65 /* static guint signals[LAST_SIGNAL] = {0}; */
66
67 GType
68 modest_edit_msg_window_get_type (void)
69 {
70         static GType my_type = 0;
71         if (!my_type) {
72                 static const GTypeInfo my_info = {
73                         sizeof(ModestEditMsgWindowClass),
74                         NULL,           /* base init */
75                         NULL,           /* base finalize */
76                         (GClassInitFunc) modest_edit_msg_window_class_init,
77                         NULL,           /* class finalize */
78                         NULL,           /* class data */
79                         sizeof(ModestEditMsgWindow),
80                         1,              /* n_preallocs */
81                         (GInstanceInitFunc) modest_edit_msg_window_init,
82                         NULL
83                 };
84                 my_type = g_type_register_static (GTK_TYPE_WINDOW,
85                                                   "ModestEditMsgWindow",
86                                                   &my_info, 0);
87         }
88         return my_type;
89 }
90
91 static void
92 modest_edit_msg_window_class_init (ModestEditMsgWindowClass *klass)
93 {
94         GObjectClass *gobject_class;
95         gobject_class = (GObjectClass*) klass;
96
97         parent_class            = g_type_class_peek_parent (klass);
98         gobject_class->finalize = modest_edit_msg_window_finalize;
99
100         g_type_class_add_private (gobject_class, sizeof(ModestEditMsgWindowPrivate));
101
102         /* signal definitions go here, e.g.: */
103 /*      signals[MY_SIGNAL_1] = */
104 /*              g_signal_new ("my_signal_1",....); */
105 /*      signals[MY_SIGNAL_2] = */
106 /*              g_signal_new ("my_signal_2",....); */
107 /*      etc. */
108 }
109
110 static void
111 modest_edit_msg_window_init (ModestEditMsgWindow *obj)
112 {
113         ModestEditMsgWindowPrivate *priv;
114         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
115
116         priv->factory = NULL;
117         priv->toolbar = NULL;
118         priv->menubar = NULL;
119                 
120 }
121
122
123
124
125
126
127 /* Our menu, an array of GtkItemFactoryEntry structures that defines each menu item */
128 static GtkItemFactoryEntry menu_items[] = {
129         { "/_File",             NULL,                   NULL,           0, "<Branch>" },
130         { "/File/_New",         "<control>N",           NULL,           0, "<StockItem>", GTK_STOCK_NEW },
131         { "/File/_Open",        "<control>O",           NULL,           0, "<StockItem>", GTK_STOCK_OPEN },
132         { "/File/_Save",        "<control>S",           NULL,           0, "<StockItem>", GTK_STOCK_SAVE },
133         { "/File/Save _As",     NULL,                   NULL,           0, "<Item>" },
134         { "/File/Save Draft",   "<control><shift>S",    NULL,           0, "<Item>" },
135
136
137         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>" },
138         { "/File/_Quit",        "<CTRL>Q",              NULL,           0, "<StockItem>", GTK_STOCK_QUIT },
139
140         { "/_Edit",             NULL,                   NULL,           0, "<Branch>" },
141         { "/Edit/_Undo",        "<CTRL>Z",              NULL,           0, "<StockItem>", GTK_STOCK_UNDO },
142         { "/Edit/_Redo",        "<shift><CTRL>Z",       NULL,           0, "<StockItem>", GTK_STOCK_REDO },
143         { "/File/sep1",         NULL,                   NULL,           0, "<Separator>" },
144         { "/Edit/Cut",          "<control>X",           NULL,           0, "<StockItem>", GTK_STOCK_CUT  },
145         { "/Edit/Copy",         "<CTRL>C",              NULL,           0, "<StockItem>", GTK_STOCK_COPY },
146         { "/Edit/Paste",        NULL,                   NULL,           0, "<StockItem>", GTK_STOCK_PASTE},
147         { "/Edit/sep1",         NULL,                   NULL,           0, "<Separator>" },
148         { "/Edit/Delete",       "<CTRL>Q",              NULL,           0, "<Item>" },
149         { "/Edit/Select all",   "<CTRL>A",              NULL,           0, "<Item>" },
150         { "/Edit/Deselect all",  "<Shift><CTRL>A",      NULL,           0, "<Item>" },
151
152         { "/_View",             NULL,           NULL,           0, "<Branch>" },
153         { "/View/To-field",          NULL,              NULL,           0, "<Item>" },
154         
155         { "/View/Cc-field:",          NULL,             NULL,           0, "<Item>" },
156         { "/View/Bcc-field:",          NULL,            NULL,           0, "<Item>" },
157         
158         
159         { "/_Insert",             NULL,         NULL,           0, "<Branch>" },
160 /*      { "/Actions/_Reply",    NULL,                   NULL,           0, "<Item>" }, */
161 /*      { "/Actions/_Forward",  NULL,                   NULL,           0, "<Item>" }, */
162 /*      { "/Actions/_Bounce",   NULL,                   NULL,           0, "<Item>" },   */
163         
164         { "/_Format",            NULL,                  NULL,           0, "<Branch>" }
165 /*      { "/Options/_Accounts",  NULL,                  on_menu_accounts,0, "<Item>" }, */
166 /*      { "/Options/_Contacts",  NULL,                  NULL,           0, "<Item>" }, */
167
168
169 /*      { "/_Help",         NULL,                       NULL,           0, "<Branch>" }, */
170 /*      { "/_Help/About",   NULL,                       on_menu_about,  0, "<StockItem>", GTK_STOCK_ABOUT}, */
171 };
172
173 static gint nmenu_items = sizeof (menu_items) / sizeof (menu_items[0]);
174
175
176 static GtkWidget *
177 menubar_new (ModestEditMsgWindow *self)
178 {
179         GtkItemFactory *item_factory;
180         GtkAccelGroup *accel_group;
181         
182         /* Make an accelerator group (shortcut keys) */
183         accel_group = gtk_accel_group_new ();
184         
185         /* Make an ItemFactory (that makes a menubar) */
186         item_factory = gtk_item_factory_new (GTK_TYPE_MENU_BAR, "<main>",
187                                              accel_group);
188         
189         /* This function generates the menu items. Pass the item factory,
190            the number of items in the array, the array itself, and any
191            callback data for the the menu items. */
192         gtk_item_factory_create_items (item_factory, nmenu_items, menu_items, self);
193         
194         ///* Attach the new accelerator group to the window. */
195         gtk_window_add_accel_group (GTK_WINDOW (self), accel_group);
196         
197         /* Finally, return the actual menu bar created by the item factory. */
198         return gtk_item_factory_get_widget (item_factory, "<main>");
199 }
200
201
202
203 static void
204 on_toolbar_button_clicked (ModestToolbar *toolbar, ModestToolbarButton button_id,
205                            ModestEditMsgWindow *self)
206 {
207         switch (button_id) {
208         case MODEST_TOOLBAR_BUTTON_MAIL_SEND:
209                 g_warning ("send the mail!");
210                 gtk_widget_destroy (GTK_WIDGET(self));
211                 break;
212                 
213         case MODEST_TOOLBAR_BUTTON_REPLY:
214         case MODEST_TOOLBAR_BUTTON_REPLY_ALL:
215         case MODEST_TOOLBAR_BUTTON_FORWARD:
216         case MODEST_TOOLBAR_BUTTON_SEND_RECEIVE:
217         case MODEST_TOOLBAR_BUTTON_NEXT:
218         case MODEST_TOOLBAR_BUTTON_PREV:
219         case MODEST_TOOLBAR_BUTTON_DELETE:
220
221         default:
222                 g_printerr ("modest: key %d pressed\n", button_id);
223         }
224 }
225
226
227
228
229 static ModestToolbar*
230 toolbar_new (ModestEditMsgWindow *self)
231 {
232         int i;
233         ModestToolbar *toolbar;
234         GSList *buttons = NULL;
235         ModestEditMsgWindowPrivate *priv;
236
237         ModestToolbarButton button_ids[] = {
238                 MODEST_TOOLBAR_BUTTON_MAIL_SEND
239         };              
240         
241         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
242
243         for (i = 0 ; i != sizeof(button_ids) / sizeof(ModestToolbarButton); ++i)
244                 buttons = g_slist_append (buttons, GINT_TO_POINTER(button_ids[i]));
245         
246         toolbar = modest_widget_factory_get_edit_toolbar (priv->factory, buttons);
247         g_slist_free (buttons);
248
249         g_signal_connect (G_OBJECT(toolbar), "button_clicked",
250                           G_CALLBACK(on_toolbar_button_clicked), self);
251         
252         return toolbar;
253 }
254
255
256 static void
257 init_window (ModestEditMsgWindow *obj)
258 {
259         GtkWidget *to_button, *cc_button, *bcc_button, *subject_label; 
260         GtkWidget *header_table;
261         GtkWidget *main_vbox;
262         
263         ModestEditMsgWindowPrivate *priv;
264         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
265
266         to_button     = gtk_button_new_with_label (_("To..."));
267         cc_button     = gtk_button_new_with_label (_("Cc..."));
268         bcc_button    = gtk_button_new_with_label (_("Bcc..."));
269         subject_label = gtk_label_new (_("Subject:"));
270         
271         priv->to_field      = gtk_entry_new_with_max_length (40);
272         priv->cc_field      = gtk_entry_new_with_max_length (40);
273         priv->bcc_field     = gtk_entry_new_with_max_length (40);
274         priv->subject_field = gtk_entry_new_with_max_length (40);
275
276         header_table = gtk_table_new (4,2, FALSE);
277         gtk_table_attach (GTK_TABLE(header_table), to_button,     0,1,0,1,
278                           GTK_SHRINK, 0, 0, 0);
279         gtk_table_attach (GTK_TABLE(header_table), cc_button,     0,1,1,2,
280                           GTK_SHRINK, 0, 0, 0);
281         gtk_table_attach (GTK_TABLE(header_table), bcc_button,    0,1,2,3,
282                           GTK_SHRINK, 0, 0, 0);
283         gtk_table_attach (GTK_TABLE(header_table), subject_label, 0,1,3,4,
284                           GTK_SHRINK, 0, 0, 0);
285  
286         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->to_field,     1,2,0,1);
287         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->cc_field,     1,2,1,2);
288         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->bcc_field,    1,2,2,3);
289         gtk_table_attach_defaults (GTK_TABLE(header_table), priv->subject_field,1,2,3,4);
290
291         priv->msg_body = gtk_text_view_new ();
292         
293         main_vbox = gtk_vbox_new  (FALSE, 6);
294
295         priv->menubar = menubar_new (obj);
296         priv->toolbar = GTK_WIDGET(toolbar_new (obj));
297
298         gtk_box_pack_start (GTK_BOX(main_vbox), priv->menubar, FALSE, FALSE, 0);
299         gtk_box_pack_start (GTK_BOX(main_vbox), priv->toolbar, FALSE, FALSE, 0);
300         gtk_box_pack_start (GTK_BOX(main_vbox), header_table, FALSE, FALSE, 0);
301         gtk_box_pack_start (GTK_BOX(main_vbox), priv->msg_body, TRUE, TRUE, 6);
302
303         gtk_widget_show_all (GTK_WIDGET(main_vbox));
304         gtk_container_add (GTK_CONTAINER(obj), main_vbox);
305 }
306         
307
308
309 static void
310 modest_edit_msg_window_finalize (GObject *obj)
311 {
312         ModestEditMsgWindowPrivate *priv;
313
314         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
315
316         g_object_unref (G_OBJECT(priv->conf));
317         priv->conf = NULL;
318
319         g_object_unref (G_OBJECT(priv->factory));
320         priv->factory = NULL;
321         
322         G_OBJECT_CLASS(parent_class)->finalize (obj);
323
324 }
325
326
327
328 static gboolean
329 on_delete_event (GtkWidget *widget, GdkEvent *event, ModestEditMsgWindow *self)
330 {
331         ModestEditMsgWindowPrivate *priv;
332         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(self);
333         
334         modest_widget_memory_save_settings (priv->conf,
335                                             GTK_WIDGET(priv->msg_body),
336                                             "modest-edit-msg-body");
337         return FALSE;
338 }
339
340
341 GtkWidget*
342 modest_edit_msg_window_new (ModestConf *conf, ModestWidgetFactory *factory,
343                             ModestEditType type, TnyMsgIface *msg)
344 {
345         GObject *obj;
346         ModestEditMsgWindowPrivate *priv;
347
348         g_return_val_if_fail (conf, NULL);
349         g_return_val_if_fail (factory, NULL);
350         g_return_val_if_fail (type >= 0 && type < MODEST_EDIT_TYPE_NUM, NULL);
351         g_return_val_if_fail (!(type==MODEST_EDIT_TYPE_NEW && msg), NULL); 
352         g_return_val_if_fail (!(type!=MODEST_EDIT_TYPE_NEW && !msg), NULL);     
353         
354         obj = g_object_new(MODEST_TYPE_EDIT_MSG_WINDOW, NULL);
355         priv = MODEST_EDIT_MSG_WINDOW_GET_PRIVATE(obj);
356
357         g_object_ref (G_OBJECT(conf));
358         priv->conf = conf;
359
360         g_object_ref (factory);
361         priv->factory = factory;
362
363         init_window (MODEST_EDIT_MSG_WINDOW(obj));
364         
365         modest_widget_memory_restore_settings (priv->conf, GTK_WIDGET(obj),
366                                                "modest-edit-msg-body");
367         
368         gtk_window_set_title (GTK_WINDOW(obj), "Modest");
369         gtk_window_set_icon  (GTK_WINDOW(obj),
370                               modest_icon_factory_get_icon (MODEST_APP_ICON));
371
372         g_signal_connect (G_OBJECT(obj), "delete-event",
373                           G_CALLBACK(on_delete_event), obj);
374         
375         return GTK_WIDGET (obj);
376 }