Merge branch 'master' into gregoa
[gregoa/zavai.git] / src / app.vala
1 /*
2  * app - zavai main window
3  *
4  * Copyright (C) 2009-2010  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
25 public class Zavai : Gtk.Window, zavai.Resource
26 {
27     public bool visibility = true;
28     public signal void visibility_changed(bool visible);
29
30     zavai.Applet current;
31
32     public Zavai()
33     {
34         title = "Zavai";
35         current = null;
36         destroy += Gtk.main_quit;
37         set_events(get_events() | Gdk.EventMask.VISIBILITY_NOTIFY_MASK);
38         set_position(Gtk.WindowPosition.MOUSE);
39         visibility_notify_event += on_visibility;
40         set_skip_pager_hint(true);
41         set_skip_taskbar_hint(true);
42         //set_type_hint(Gdk.WindowTypeHint.DESKTOP);
43
44         zavai.registry.register(this);
45     }
46
47     private bool on_visibility(Gdk.Event event)
48     {
49         visibility = (event.visibility.state == Gdk.VisibilityState.UNOBSCURED);
50         //visible = visibility;
51         visibility_changed(visibility);
52         return true;
53     }
54
55     public void toggle_visibility()
56     {
57         if (visibility)
58         {
59             visible = false;
60             visibility = false;
61             visibility_changed(visibility);
62             //zavai.app.iconify();
63         } else {
64             visible = true;
65             present();
66             set_skip_pager_hint(true);
67             set_skip_taskbar_hint(true);
68         }
69     }
70
71     public void ensure_visible()
72     {
73         if (!visibility)
74         {
75             visible = true;
76             present();
77             set_skip_pager_hint(true);
78             set_skip_taskbar_hint(true);
79         }
80     }
81
82     public void ensure_hidden()
83     {
84         if (visibility)
85         {
86             visible = false;
87             visibility = false;
88             visibility_changed(visibility);
89         }
90     }
91
92     public void show_applet(Applet applet)
93     {
94         // Remove the current applet
95         if (current != null)
96         {
97             current.stop();
98             remove(current);
99             current = null;
100         }
101
102         // Add the new applet
103         current = applet;
104         add(current);
105         current.start();
106         current.show_all();
107     }
108
109     public void push_applet(Applet applet)
110     {
111         // Make the function idempotent
112         if (current == applet)
113             return;
114
115         // Remove the current applet
116         if (current != null)
117         {
118 //stderr.printf("push applet remove %s\n", current_name);
119             applet.back_link = current;
120             current.stop();
121             remove(current);
122             current = null;
123         }
124
125 //stderr.printf("push applet add %s\n", name);
126         // Add the new applet
127         current = applet;
128         add(current);
129         current.start();
130         current.show_all();
131     }
132
133     public void back()
134     {
135         if (current != null)
136             current.back();
137     }
138
139     public void back_to_main()
140     {
141         show_applet(zavai.ui.main.status);
142     }
143
144     public void shutdown()
145     {
146     }
147
148     public void run()
149     {
150         set_size_request(300, 500);
151         //fullscreen();
152         if (zavai.config.profile == "laptop")
153         {
154             visibility = false;
155             zavai.app.ensure_hidden();
156             zavai.ui.wm.raise_icon.update_icon();
157         } else {
158             show_all();
159         }
160     }
161
162     public void run_script(string command)
163     {
164         zavai.log.info("Run program: " + command);
165         string[] args = command.split(" ");
166         Pid pid;
167         try {
168             Process.spawn_async(
169                 Environment.get_home_dir(),
170                 args,
171                 null,
172                 SpawnFlags.SEARCH_PATH,
173                 null,
174                 out pid);
175         } catch (SpawnError e) {
176             zavai.log.error("Running " + command + ": " + e.message);
177         }
178     }
179
180     public int run_script_sync(string command, out string std_out, out string std_err)
181     {
182         int status = -1;
183         zavai.log.info("Run program: " + command);
184         string[] args = command.split(" ");
185         try {
186             bool res = Process.spawn_sync(Environment.get_home_dir(), args, null, SpawnFlags.SEARCH_PATH, null, out std_out, out std_err, out status);
187         } catch (SpawnError e) {
188             zavai.log.error("Running " + command + ": " + e.message);
189         }
190         return status;
191     }
192 }
193
194 public abstract class Applet : Gtk.VBox, Resource
195 {
196     // 'label' property: label to show in window title or button names
197     protected string _label;
198     public string label {
199         get { return this._label; }
200         set {
201             if (_label != value)
202             {
203                 _label = value;
204                 label_changed();
205             }
206         }
207     }
208     public signal void label_changed();
209
210     protected Gtk.HBox button_box;
211
212     // 'back_link' property: link to use to "go back". If null, do not show
213     // a way to go back.
214     protected AppletLink _back_link = null;
215     public Applet back_link {
216         get { return _back_link.target; }
217         set {
218 //stderr.printf("Set back link of %s to %s\n", _label, value);
219             if (value == null && _back_link != null)
220             {
221                 _back_link.target = value;
222                 button_box.remove(_back_link);
223             } else if (value != null) {
224                 if (_back_link.target == null)
225                 {
226                     _back_link.target = value;
227                     button_box.pack_end(_back_link, true, true, 0);
228                     _back_link.show();
229                 } else
230                     _back_link.target = value;
231             }
232         }
233     }
234
235     public Applet()
236     {
237         button_box = new Gtk.HBox(true, 0);
238         this.homogeneous = false;
239         this.spacing = 0;
240         pack_end(button_box, false, true, 0);
241         _back_link = new AppletStraightLink();
242         zavai.registry.register(this);
243     }
244
245     public virtual void back()
246     {
247         _back_link.activate_applet();
248     }
249
250     public virtual void back_to_main()
251     {
252         zavai.app.back_to_main();
253     }
254
255     public void shutdown()
256     {
257         stop();
258     }
259
260     public virtual void start() {}
261     public virtual void stop() {}
262 }
263
264 public class Menu : Applet
265 {
266     public Menu(string label)
267     {
268         _label = label;
269     }
270
271     public void add_applet(Applet target)
272     {
273         pack_start(new AppletPushLink(target), false, false, 0);
274     }
275
276     public void add_service_toggle(Service service, string label_start, string label_stop)
277     {
278         pack_start(new ServiceRequestLink(service, label_start, label_stop), false, false, 0);
279     }
280
281     public void add_widget(Gtk.Widget w)
282     {
283         pack_start(w, false, false, 0);
284     }
285 }
286
287 public class BigButton : Gtk.Button
288 {
289     public BigButton()
290     {
291         set_size_request(0, zavai.config.min_button_height);
292     }
293 }
294
295 public abstract class AppletLink : BigButton
296 {
297     protected Applet _target;
298     public Applet target {
299         get { return _target; }
300         set
301         {
302             if (_target != null)
303             {
304                 _target.label_changed -= on_label_changed;
305             }
306             bool was_shown = _target != null;
307             _target = value;
308             if (_target != null)
309             {
310                 set_label(_target.label);
311                 _target.label_changed += on_label_changed;
312                 if (!was_shown) show();
313             } else {
314                 if (was_shown) hide();
315             }
316         }
317     }
318
319     private void on_label_changed(Applet a)
320     {
321         set_label(a.label);
322     }
323
324     private abstract void on_clicked(Gtk.Button src);
325
326     public AppletLink(Applet? applet = null)
327     {
328         _target = null;
329         target = applet;
330
331         clicked += on_clicked;
332     }
333
334     public virtual void activate_applet()
335     {
336         on_clicked(this);
337     }
338 }
339
340 public class AppletStraightLink : AppletLink
341 {
342     private override void on_clicked(Gtk.Button src)
343     {
344 //stderr.printf("straight link: %s\n", _target);
345         if (_target != null)
346             zavai.app.show_applet(_target);
347     }
348
349     public AppletStraightLink(Applet? applet = null)
350     {
351         base(applet);
352     }
353 }
354
355 public class AppletPushLink : AppletLink
356 {
357     private override void on_clicked(Gtk.Button src)
358     {
359 //stderr.printf("push link: %s\n", _target);
360         if (_target != null)
361             zavai.app.push_applet(_target);
362     }
363
364     public AppletPushLink(Applet? applet = null)
365     {
366         base(applet);
367     }
368 }
369
370 public class ServiceRequestLink : Gtk.ToggleButton
371 {
372     protected Service service;
373     protected string label_start;
374     protected string label_stop;
375
376     private void on_toggled(Gtk.Button src)
377     {
378         if (get_active())
379             service.request("servicerequestlink");
380         else
381             service.release("servicerequestlink");
382         set_label(get_active() ? label_stop : label_start);
383     }
384
385     private void on_service_toggled(bool val)
386     {
387         set_active(val);
388         //set_label(val ? label_stop : label_start);
389     }
390
391     public ServiceRequestLink(Service service, string label_start, string label_stop)
392     {
393         this.service = service;
394         this.label_start = label_start;
395         this.label_stop = label_stop;
396         set_size_request(0, zavai.config.min_button_height);
397         set_active(service.started);
398         toggled += on_toggled;
399         service.toggled += on_service_toggled;
400
401         set_label(get_active() ? label_stop : label_start);
402     }
403 }
404
405 public class StatusIcon : Gtk.Button
406 {
407     private Gtk.Image image_widget;
408
409     public StatusIcon()
410     {
411         relief = Gtk.ReliefStyle.NONE;
412         image_widget = new Gtk.Image();
413         image = image_widget;
414     }
415
416     public void set_from_file(string file)
417     {
418         image_widget.set_from_file(file);
419     }
420
421     public void install()
422     {
423         zavai.ui.main.status.status_icons.pack_start(this, false, false, 0);
424     }
425 }
426
427
428 public zavai.Zavai app;
429 public zavai.Menu menu_main;
430 public zavai.Menu menu_gps;
431 public zavai.Menu menu_gsm;
432 public zavai.Menu menu_misc;
433
434 namespace main {
435
436 public void init()
437 {
438     zavai.app = new zavai.Zavai();
439     menu_main = new zavai.Menu("Main menu");
440
441     // Create menus
442     menu_gps = new zavai.Menu("GPS");
443     menu_main.add_applet(menu_gps);
444
445     menu_gsm = new zavai.Menu("GSM");
446     menu_main.add_applet(menu_gsm);
447
448     menu_misc = new zavai.Menu("Misc");
449     menu_main.add_applet(menu_misc);
450 }
451
452 }
453
454 }