add widgets to the main window
[milk] / src / milk-main-window.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License as
4  * published by the Free Software Foundation; either version 2 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10  * General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public
13  * License along with this program; if not, write to the
14  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
15  * Boston, MA  02110-1301  USA
16  *
17  * Authors: Travis Reitter <treitter@gmail.com>
18  */
19
20 #include <config.h>
21
22 #include <glib.h>
23 #include <glib/gi18n.h>
24 #include <gtk/gtk.h>
25 #include <hildon/hildon.h>
26
27 #include "milk-main-window.h"
28
29 G_DEFINE_TYPE (MilkMainWindow, milk_main_window, HILDON_TYPE_WINDOW)
30
31 #define MILK_MAIN_WINDOW_PRIVATE(o) \
32                 (G_TYPE_INSTANCE_GET_PRIVATE ((o), MILK_TYPE_MAIN_WINDOW, MilkMainWindowPrivate))
33
34 struct _MilkMainWindowPrivate
35 {
36         GtkWidget *main_vbox;
37
38         GtkWidget *new_task_entry;
39         GtkWidget *task_view;
40         GtkWidget *action_bar;
41 };
42
43 static void
44 milk_main_window_get_property (GObject    *object,
45                                guint       property_id,
46                                GValue     *value,
47                                GParamSpec *pspec)
48 {
49         switch (property_id)
50         {
51                 default:
52                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
53                                         pspec);
54         }
55 }
56
57 static void
58 milk_main_window_set_property (GObject      *object,
59                                guint         property_id,
60                                const GValue *value,
61                                GParamSpec   *pspec)
62 {
63         switch (property_id)
64         {
65                 default:
66                         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id,
67                                         pspec);
68         }
69 }
70
71 static void
72 milk_main_window_dispose (GObject *object)
73 {
74         G_OBJECT_CLASS (milk_main_window_parent_class)->dispose (object);
75 }
76
77 static void
78 complete_clicked_cb (GtkButton      *button,
79                      MilkMainWindow *window)
80 {
81         g_debug ("FIXME: implement 'complete' action");
82 }
83
84 static void
85 delete_clicked_cb (GtkButton      *button,
86                    MilkMainWindow *window)
87 {
88         g_debug ("FIXME: implement 'delete' action");
89 }
90
91 static void
92 priority_plus_clicked_cb (GtkButton      *button,
93                           MilkMainWindow *window)
94 {
95         g_debug ("FIXME: implement 'priority plus' action");
96 }
97
98 static void
99 priority_minus_clicked_cb (GtkButton      *button,
100                            MilkMainWindow *window)
101 {
102         g_debug ("FIXME: implement 'priority minus' action");
103 }
104
105 static void
106 edit_clicked_cb (GtkButton      *button,
107                  MilkMainWindow *window)
108 {
109         g_debug ("FIXME: implement 'edit' action");
110 }
111
112 static MenuItem menu_items_always_shown[] = {
113         {"New Task",   "menu-item-new-task",       new_task_clicked_cb},
114 };
115
116 static MenuItem menu_items_selection_required[] = {
117         {"Edit",       "menu-item-edit",           edit_clicked_cb},
118         {"Priority +", "menu-item-priority_plus",  priority_plus_clicked_cb},
119         {"Priority -", "menu-item-priority_minus", priority_minus_clicked_cb},
120         {"Complete",   "menu-item-complete",       complete_clicked_cb},
121         {"Delete",     "menu-item-delete",         delete_clicked_cb},
122 };
123
124 static void
125 task_view_selection_changed_cb (HildonTouchSelector *view,
126                                 gint                 column,
127                                 MilkMainWindow      *window)
128 {
129         MilkMainWindowPrivate *priv;
130         GList *rows;
131         gboolean show = FALSE;
132         gint i;
133
134         priv = MILK_MAIN_WINDOW_PRIVATE (window);
135
136         rows = hildon_touch_selector_get_selected_rows (view, column);
137         show = (g_list_length (rows) > 0);
138
139         for (i = 0; i < G_N_ELEMENTS (menu_items_selection_required); i++) {
140                 GtkWidget *w;
141
142                 w = g_object_get_data (
143                                 G_OBJECT (priv->app_menu),
144                                 menu_items_selection_required[i].id);
145
146                 if (show)
147                         gtk_widget_show (w);
148                 else
149                         gtk_widget_hide (w);
150         }
151 }
152
153 static GtkWidget*
154 create_menu (gpointer user_data)
155 {
156         HildonAppMenu *menu;
157         MenuItem *menu_array;
158         gint i, length;
159         GtkWidget *w;
160
161         menu = HILDON_APP_MENU (hildon_app_menu_new ());
162
163         menu_array = menu_items_always_shown;
164         length = G_N_ELEMENTS (menu_items_always_shown);
165         for (i = 0; i < length; i++) {
166                 w = hildon_button_new_with_text (
167                                 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
168                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
169                                 _(menu_array[i].display_name), "");
170                 g_signal_connect (w, "clicked",
171                                 G_CALLBACK (menu_array[i].callback), user_data);
172                 g_object_set_data (G_OBJECT (menu), menu_array[i].id, w);
173                 hildon_app_menu_append (menu, GTK_BUTTON (w));
174                 gtk_widget_show (w);
175         }
176
177         menu_array = menu_items_selection_required;
178         length = G_N_ELEMENTS (menu_items_selection_required);
179         for (i = 0; i < length; i++) {
180                 w = hildon_button_new_with_text (
181                                 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
182                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
183                                 menu_array[i].display_name, "");
184                 g_signal_connect (w, "clicked",
185                                 G_CALLBACK (menu_array[i].callback), user_data);
186                 g_object_set_data (G_OBJECT (menu), menu_array[i].id, w);
187                 hildon_app_menu_append (menu, GTK_BUTTON (w));
188                 gtk_widget_hide (w);
189         }
190
191         gtk_widget_show (GTK_WIDGET (menu));
192
193         return GTK_WIDGET (menu);
194 }
195
196 static MenuItem menu_items_always_shown[] = {
197         {"New Task",   "menu-item-new-task",       new_task_clicked_cb},
198 };
199
200 static MenuItem menu_items_selection_required[] = {
201         {"Edit",       "menu-item-edit",           edit_clicked_cb},
202         {"Priority +", "menu-item-priority_plus",  priority_plus_clicked_cb},
203         {"Priority -", "menu-item-priority_minus", priority_minus_clicked_cb},
204         {"Complete",   "menu-item-complete",       complete_clicked_cb},
205         {"Delete",     "menu-item-delete",         delete_clicked_cb},
206 };
207
208 static void
209 task_view_selection_changed_cb (HildonTouchSelector *view,
210                                 gint                 column,
211                                 MilkMainWindow      *window)
212 {
213         MilkMainWindowPrivate *priv;
214         GList *rows;
215         gboolean show = FALSE;
216         gint i;
217
218         priv = MILK_MAIN_WINDOW_PRIVATE (window);
219
220         rows = hildon_touch_selector_get_selected_rows (view, column);
221         show = (g_list_length (rows) > 0);
222
223         for (i = 0; i < G_N_ELEMENTS (menu_items_selection_required); i++) {
224                 GtkWidget *w;
225
226                 w = g_object_get_data (
227                                 G_OBJECT (priv->app_menu),
228                                 menu_items_selection_required[i].id);
229
230                 if (show)
231                         gtk_widget_show (w);
232                 else
233                         gtk_widget_hide (w);
234         }
235 }
236
237 static GtkWidget*
238 create_menu (gpointer user_data)
239 {
240         HildonAppMenu *menu;
241         MenuItem *menu_array;
242         gint i, length;
243         GtkWidget *w;
244
245         menu = HILDON_APP_MENU (hildon_app_menu_new ());
246
247         menu_array = menu_items_always_shown;
248         length = G_N_ELEMENTS (menu_items_always_shown);
249         for (i = 0; i < length; i++) {
250                 w = hildon_button_new_with_text (
251                                 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
252                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
253                                 _(menu_array[i].display_name), "");
254                 g_signal_connect (w, "clicked",
255                                 G_CALLBACK (menu_array[i].callback), user_data);
256                 g_object_set_data (G_OBJECT (menu), menu_array[i].id, w);
257                 hildon_app_menu_append (menu, GTK_BUTTON (w));
258                 gtk_widget_show (w);
259         }
260
261         menu_array = menu_items_selection_required;
262         length = G_N_ELEMENTS (menu_items_selection_required);
263         for (i = 0; i < length; i++) {
264                 w = hildon_button_new_with_text (
265                                 HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
266                                 HILDON_BUTTON_ARRANGEMENT_VERTICAL,
267                                 menu_array[i].display_name, "");
268                 g_signal_connect (w, "clicked",
269                                 G_CALLBACK (menu_array[i].callback), user_data);
270                 g_object_set_data (G_OBJECT (menu), menu_array[i].id, w);
271                 hildon_app_menu_append (menu, GTK_BUTTON (w));
272                 gtk_widget_hide (w);
273         }
274
275         gtk_widget_show (GTK_WIDGET (menu));
276
277         return GTK_WIDGET (menu);
278 }
279
280 static void
281 contact_column_render_func (GtkCellLayout   *cell_layout,
282                             GtkCellRenderer *renderer,
283                             GtkTreeModel    *model,
284                             GtkTreeIter     *iter,
285                             gpointer         user_data)
286 {
287         MilkTask *task;
288         char *title;
289
290         gtk_tree_model_get (
291                         model, iter, MILK_TASK_MODEL_COLUMN_TASK, &task, -1);
292
293         g_object_get (task, "title", &title, NULL);
294         g_object_set (renderer, "text", title, NULL);
295
296         g_free (title);
297         g_object_unref (task);
298 }
299
300 static void
301 milk_main_window_constructed (GObject* object)
302 {
303         MilkMainWindow *self = MILK_MAIN_WINDOW (object);
304         MilkMainWindowPrivate *priv = MILK_MAIN_WINDOW_PRIVATE (object);
305         GtkWidget *w;
306         GtkWidget *pannable;
307
308         w = gtk_vbox_new (FALSE, HILDON_MARGIN_DEFAULT);
309         gtk_container_add (GTK_CONTAINER (self), w);
310         priv->main_vbox = w;
311
312         /*
313          * New Task entry
314          */
315         w = hildon_entry_new (HILDON_SIZE_FINGER_HEIGHT);
316         gtk_box_pack_start (GTK_BOX (priv->main_vbox), w, FALSE, FALSE, 0);
317
318         /* FIXME: change this to hildon_gtk_entry_set_placeholder_text() is
319          * fixed, since this is deprecated */
320         hildon_entry_set_placeholder (HILDON_ENTRY (w),
321                         _("Enter a new task..."));
322         priv->new_task_entry = w;
323
324         /*
325          * Task List
326          */
327         w = hildon_pannable_area_new ();
328         gtk_box_pack_start (GTK_BOX (priv->main_vbox), w, TRUE, TRUE, 0);
329         pannable = w;
330
331         /* FIXME: attach the model (create a new MilkTaskModel class that syncs
332          * with the cached tasks) */
333         w = gtk_tree_view_new ();
334         hildon_pannable_area_add_with_viewport (HILDON_PANNABLE_AREA (pannable),
335                         w);
336         gtk_widget_grab_focus (w);
337         priv->task_view = w;
338
339         /*
340          * Action Bar
341          */
342         w = gtk_hbox_new (TRUE, HILDON_MARGIN_DEFAULT);
343         gtk_box_pack_start (GTK_BOX (priv->main_vbox), w, FALSE, FALSE, 0);
344         priv->action_bar = w;
345
346         /* FIXME: these are probably better off being icons, for width reasons
347          */
348         w = hildon_button_new_with_text (
349                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
350                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
351                         _("Complete"), "");
352         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
353         g_signal_connect (w, "clicked", G_CALLBACK (complete_clicked_cb), self);
354
355         w = hildon_button_new_with_text (
356                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
357                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
358                         _("Delete"), "");
359         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
360         g_signal_connect (w, "clicked", G_CALLBACK (delete_clicked_cb), self);
361
362         w = hildon_button_new_with_text (
363                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
364                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
365                         _("Priority +"), "");
366         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
367         g_signal_connect (w, "clicked", G_CALLBACK (priority_plus_clicked_cb),
368                         self);
369
370         w = hildon_button_new_with_text (
371                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
372                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
373                         _("Priority -"), "");
374         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
375         g_signal_connect (w, "clicked", G_CALLBACK (priority_minus_clicked_cb),
376                         self);
377
378         w = hildon_button_new_with_text (
379                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
380                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
381                         _("Edit"), "");
382         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
383         g_signal_connect (w, "clicked", G_CALLBACK (edit_clicked_cb),
384                         self);
385
386         w = hildon_button_new_with_text (
387                         HILDON_SIZE_FINGER_HEIGHT | HILDON_SIZE_AUTO_WIDTH,
388                         HILDON_BUTTON_ARRANGEMENT_VERTICAL,
389                         _("Edit Tags"), "");
390         gtk_container_add (GTK_CONTAINER (priv->action_bar), w);
391         g_signal_connect (w, "clicked", G_CALLBACK (edit_tags_clicked_cb),
392                         self);
393 }
394
395 static void
396 milk_main_window_class_init (MilkMainWindowClass *klass)
397 {
398         GObjectClass *object_class = G_OBJECT_CLASS (klass);
399
400         g_type_class_add_private (klass, sizeof (MilkMainWindowPrivate));
401
402         object_class->get_property = milk_main_window_get_property;
403         object_class->set_property = milk_main_window_set_property;
404         object_class->constructed = milk_main_window_constructed;
405         object_class->dispose = milk_main_window_dispose;
406 }
407
408 static void
409 milk_main_window_init (MilkMainWindow *self)
410 {
411         self->priv = MILK_MAIN_WINDOW_PRIVATE (self);
412 }
413
414 GtkWidget*
415 milk_main_window_new ()
416 {
417         return g_object_new (MILK_TYPE_MAIN_WINDOW,
418                              NULL);
419 }