b293cab1bb0ef45ac0cd67269be06f71af6be86d
[gregoa/zavai.git] / src / app_main.vala
1 /*
2  * app_main - zavai main status display
3  *
4  * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace ui {
25 namespace main {
26
27 /*
28 public class StatusBar : Gtk.HBox
29 {
30     void StatusBar()
31     {
32     }
33 }
34 */
35
36 public class Clock : Gtk.VBox
37 {
38     protected Gtk.Label l_date;
39     protected Gtk.Label l_time;
40     protected Gtk.Label l_deadline;
41     protected time_t last_time;
42     protected zavai.clock.SourceType last_time_type;
43     protected time_t last_deadline;
44     protected string last_deadline_label;
45
46     public Clock()
47     {
48         last_time = time_t();
49         last_time_type = zavai.clock.SourceType.SYSTEM;
50         last_deadline = 0;
51         last_deadline_label = "";
52
53         l_date = new Gtk.Label("--");
54         l_date.modify_font(Pango.FontDescription.from_string("Sans 40"));
55         pack_start(l_date, false, false, 0);
56         l_time = new Gtk.Label("--:--");
57         l_time.modify_font(Pango.FontDescription.from_string("Sans 60"));
58         pack_start(l_time, false, false, 0);
59         l_deadline = new Gtk.Label("");
60         l_deadline.modify_font(Pango.FontDescription.from_string("Sans 30"));
61         l_deadline.set_justify(Gtk.Justification.CENTER);
62         pack_start(l_deadline, false, false, 0);
63
64         zavai.clock.clock.minute_changed += on_minute_changed;
65         zavai.clock.clock.schedule_changed += on_schedule_changed;
66
67         zavai.clock.clock.request("ui.main.clock");
68     }
69
70     private void on_schedule_changed()
71     {
72         zavai.clock.Alarm a = zavai.clock.clock.next_alarm();
73         if (a == null)
74         {
75             last_deadline = 0;
76             last_deadline_label = "";
77         }
78         else
79         {
80             last_deadline = a.deadline;
81             last_deadline_label = a.label;
82         }
83         on_minute_changed((long)last_time, last_time_type);
84     }
85
86     private void on_minute_changed(long ts, zavai.clock.SourceType type)
87     {
88         last_time = (time_t)ts;
89         last_time_type = type;
90
91         string typetag = "unknown";
92         switch (type)
93         {
94             case zavai.clock.SourceType.GPS:
95                 typetag = "gps";
96                 break;
97             case zavai.clock.SourceType.SYSTEM:
98                 typetag = "sys";
99                 break;
100         }
101                 
102         var t = Time.local((time_t)ts);
103         l_date.set_text(t.format("%a %d %b"));
104         l_time.set_text("%2d:%02d (%s)".printf(t.hour, t.minute, typetag));
105
106         if (last_deadline == 0)
107             l_deadline.set_text("");
108         else
109         {
110             int remaining = (int)(last_deadline - last_time);
111             int hours = remaining / 3600;
112             int minutes = (remaining % 3600) / 60;
113             if (hours == 0 && minutes == 0)
114                 l_deadline.set_text(last_deadline_label + "\nanytime now");
115             else
116                 l_deadline.set_text("%s\nin %02dh %02dm".printf(last_deadline_label, hours, minutes));
117         }
118     }
119 }
120
121 public class Status : Applet
122 {
123     public Gtk.HBox status_icons;
124     public Clock clock;
125     public AppletPushLink menu;
126
127         public Status(string label)
128         {
129                 _label = label;
130         status_icons = new Gtk.HBox(false, 0);
131         clock = new Clock();
132         menu = new AppletPushLink("menu.main");
133
134                 pack_start(status_icons, false, false, 0);
135                 pack_start(clock, false, false, 0);
136                 pack_end(menu, false, false, 0);
137         }
138 }
139
140 public class IncDec : Gtk.HBox
141 {
142     protected Gtk.Button b_decmore;
143     protected Gtk.Button b_dec;
144     protected Gtk.Button b_inc;
145     protected Gtk.Button b_incmore;
146     static const int BH = 50;
147     static const int BW = 50;
148
149     public signal void tweaked(IncDec id, int amount);
150
151     public IncDec()
152     {
153         homogeneous = true;
154         b_decmore = new Gtk.Button.with_label("«");
155                 b_decmore.set_size_request(BW, BH);
156         b_dec = new Gtk.Button.with_label("<");
157                 b_dec.set_size_request(BW, BH);
158         b_inc = new Gtk.Button.with_label(">");
159                 b_inc.set_size_request(BW, BH);
160         b_incmore = new Gtk.Button.with_label("»");
161                 b_incmore.set_size_request(BW, BH);
162         pack_start(b_decmore, false, true, 0);
163         pack_start(b_dec, false, true, 0);
164         pack_start(b_inc, false, true, 0);
165         pack_start(b_incmore, false, true, 0);
166         b_decmore.clicked += on_clicked;
167         b_dec.clicked += on_clicked;
168         b_inc.clicked += on_clicked;
169         b_incmore.clicked += on_clicked;
170     }
171
172     protected void on_clicked(Gtk.Button b)
173     {
174         if (b == b_decmore)
175             tweaked(this, -10);
176         else if (b == b_dec)
177             tweaked(this, -1);
178         else if (b == b_inc)
179             tweaked(this, 1);
180         else if (b == b_incmore)
181             tweaked(this, 10);
182     }
183 }
184
185 public abstract class AddDeadline : Applet
186 {
187     protected Gtk.ComboBoxEntry dl_label;
188     protected Gtk.Button dl_submit;
189
190     public AddDeadline()
191     {
192         dl_label = new Gtk.ComboBoxEntry.text();
193         dl_label.append_text("Pasta");
194         dl_label.append_text("Talk");
195         dl_label.append_text("Leave");
196         dl_label.changed += on_label_changed;
197
198         var hbox = new Gtk.HBox(false, 0);
199         hbox.pack_start(new Gtk.Label("Label: "), false, false, 0);
200         hbox.pack_start(dl_label, true, true, 0);
201         pack_start(hbox, false, false, 0);
202
203         dl_submit = new Gtk.Button.with_label("Activate");
204         dl_submit.set_sensitive(false);
205         dl_submit.clicked += on_submit;
206         button_box.pack_start(dl_submit, true, true, 0);
207     }
208
209         public override void start()
210     {
211         ((Gtk.Entry)dl_label.get_child()).set_text("");
212         update();
213     }
214
215     protected virtual void update()
216     {
217         dl_submit.set_sensitive(((Gtk.Entry)dl_label.get_child()).get_text() == "" ? false : true);
218     }
219
220     protected abstract time_t get_deadline();
221
222     protected void on_label_changed(Gtk.ComboBox e)
223     {
224         update();
225     }
226
227     protected void on_submit(Gtk.Button b)
228     {
229         string label = ((Gtk.Entry)dl_label.get_child()).get_text();
230         zavai.log.info("Scheduling deadline " + label);
231         zavai.clock.Alarm a = new zavai.clock.Alarm(get_deadline(), label);
232         a.trigger += zavai.audio.audio.notify_alarm;
233         zavai.clock.clock.schedule(a);
234         back();
235     }
236 }
237
238 public class AddAbsoluteDeadline : AddDeadline
239 {
240     protected Gtk.Label dl_day;
241     protected IncDec dl_day_tweak;
242     protected Gtk.Label dl_hour;
243     protected IncDec dl_hour_tweak;
244     protected Gtk.Label dl_min;
245     protected IncDec dl_min_tweak;
246     protected time_t dl_time;
247
248     public AddAbsoluteDeadline()
249     {
250         _label = "Add absolute deadline";
251         dl_time = 0;
252
253         dl_day = new Gtk.Label("");
254         dl_day.set_justify(Gtk.Justification.RIGHT);
255         dl_day_tweak = new IncDec();
256         dl_day_tweak.tweaked += on_tweak;
257         var hbox = new Gtk.HBox(false, 0);
258         hbox.pack_start(new Gtk.Label("Day: "), false, false, 0);
259         hbox.pack_start(dl_day, true, true, 0);
260         hbox.pack_start(dl_day_tweak, false, false, 0);
261         pack_start(hbox, false, false, 0);
262
263         dl_hour = new Gtk.Label("");
264         dl_hour.set_justify(Gtk.Justification.RIGHT);
265         dl_hour_tweak = new IncDec();
266         dl_hour_tweak.tweaked += on_tweak;
267         hbox = new Gtk.HBox(false, 0);
268         hbox.pack_start(new Gtk.Label("Hour: "), false, false, 0);
269         hbox.pack_start(dl_hour, true, true, 0);
270         hbox.pack_start(dl_hour_tweak, false, false, 0);
271         pack_start(hbox, false, false, 0);
272
273         dl_min = new Gtk.Label("");
274         dl_min.set_justify(Gtk.Justification.RIGHT);
275         dl_min_tweak = new IncDec();
276         dl_min_tweak.tweaked += on_tweak;
277         hbox = new Gtk.HBox(false, 0);
278         hbox.pack_start(new Gtk.Label("Minute: "), false, false, 0);
279         hbox.pack_start(dl_min, true, true, 0);
280         hbox.pack_start(dl_min_tweak, false, false, 0);
281         pack_start(hbox, false, false, 0);
282     }
283
284         public override void start()
285     {
286         dl_time = time_t();
287         base.start();
288     }
289
290     protected override void update()
291     {
292         Time t = Time.local(dl_time);
293         dl_day.set_text(t.format("%a %d %b"));
294         dl_hour.set_text(t.format("%H"));
295         dl_min.set_text(t.format("%M"));
296         base.update();
297     }
298
299     protected override time_t get_deadline()
300     {
301         return dl_time;
302     }
303
304     protected void on_tweak(IncDec id, int amount)
305     {
306         time_t old = dl_time;
307         if (id == dl_day_tweak)
308             dl_time += amount * 3600 * 24;
309         else if (id == dl_hour_tweak)
310             dl_time += amount * 3600;
311         else if (id == dl_min_tweak)
312             dl_time += amount * 60;
313         time_t now = time_t();
314         if (dl_time < now)
315             dl_time = old;
316         update();
317     }
318 }
319
320 public class AddRelativeDeadline : AddDeadline
321 {
322     protected Gtk.Label dl_hour;
323     protected IncDec dl_hour_tweak;
324     protected Gtk.Label dl_min;
325     protected IncDec dl_min_tweak;
326     protected int dl_time;
327
328     public AddRelativeDeadline()
329     {
330         _label = "Add relative deadline";
331         dl_time = 0;
332
333         dl_hour = new Gtk.Label("");
334         dl_hour.set_justify(Gtk.Justification.RIGHT);
335         dl_hour_tweak = new IncDec();
336         dl_hour_tweak.tweaked += on_tweak;
337         var hbox = new Gtk.HBox(false, 0);
338         hbox.pack_start(new Gtk.Label("Hour: "), false, false, 0);
339         hbox.pack_start(dl_hour, true, true, 0);
340         hbox.pack_start(dl_hour_tweak, false, false, 0);
341         pack_start(hbox, false, false, 0);
342
343         dl_min = new Gtk.Label("");
344         dl_min.set_justify(Gtk.Justification.RIGHT);
345         dl_min_tweak = new IncDec();
346         dl_min_tweak.tweaked += on_tweak;
347         hbox = new Gtk.HBox(false, 0);
348         hbox.pack_start(new Gtk.Label("Minute: "), false, false, 0);
349         hbox.pack_start(dl_min, true, true, 0);
350         hbox.pack_start(dl_min_tweak, false, false, 0);
351         pack_start(hbox, false, false, 0);
352     }
353
354         public override void start()
355     {
356         dl_time = 0;
357         base.start();
358     }
359
360     protected override void update()
361     {
362         dl_hour.set_text("%2d".printf(dl_time/60));
363         dl_min.set_text("%2d".printf(dl_time%60));
364         base.update();
365     }
366
367     protected void on_tweak(IncDec id, int amount)
368     {
369         int old = dl_time;
370         if (id == dl_hour_tweak)
371             dl_time += amount * 60;
372         else if (id == dl_min_tweak)
373             dl_time += amount;
374         if (dl_time < 0)
375             dl_time = old;
376         update();
377     }
378
379     protected override time_t get_deadline()
380     {
381         return time_t() + dl_time * 60;
382     }
383 }
384
385 /*
386 public class AddDailyDeadline : Applet
387 {
388     public AddDailyDeadline()
389     {
390         _label = "Add daily deadline";
391     }
392 }
393 */
394
395 Status status;
396 AddAbsoluteDeadline aad;
397 AddRelativeDeadline ard;
398 //AddDailyDeadline add;
399
400 public void init()
401 {
402     status = new Status("Zavai");
403     zavai.registry.register_applet("zavai.status", status);
404
405     aad = new AddAbsoluteDeadline();
406     zavai.registry.register_applet("clock.addabsolute", aad);
407     ard = new AddRelativeDeadline();
408     zavai.registry.register_applet("clock.addrelative", ard);
409     /*
410     add = new AddDailyDeadline();
411     zavai.registry.register_applet("clock.adddaily", add);
412     */
413
414     var menu_misc = zavai.registry.getmenu("menu.misc");
415         menu_misc.add_applet("clock.addabsolute");
416         menu_misc.add_applet("clock.addrelative");
417         //menu_misc.add_applet("clock.adddaily");
418 }
419
420 }
421 }
422 }