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