Formalized plugin interface
[WebThing.git] / WebThing.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4 using System.IO;
5 using System.Text.RegularExpressions;
6 using System.Runtime.InteropServices;
7 using Gtk;
8 using GtkSharp;
9 using WebKit;
10
11 namespace bytex64.WebThing {
12     public enum CompassDirection {
13         N, E, S, W, Interior
14     }
15
16     public class WebThing {
17         public Gtk.Window Window {
18             get { return _Window; }
19         }
20
21         public Gtk.Window w {
22             get { return _Window; }
23         }
24
25         public Gtk.ScrolledWindow ScrolledWindow {
26             get { return _ScrolledWindow; }
27         }
28
29         public Gtk.ScrolledWindow sw {
30             get { return _ScrolledWindow; }
31         }
32
33         public WebKit.WebView WebView {
34             get { return _WebView; }
35         }
36
37         public WebKit.WebView wv {
38             get { return _WebView; }
39         }
40
41         private Gtk.Window _Window;
42         private ScrolledWindow _ScrolledWindow;
43         private WebKit.WebView _WebView;
44         private Gtk.Table WidgetGrid;
45         private Gtk.Alignment InteriorOverlay;
46
47         public Dictionary<string,WebThingPlugin> Plugins;
48         public Dictionary<string,string> Options;
49         public string[] Arguments;
50
51         [DllImport ("SoupSettings.dll")]
52         private static extern void soup_settings();
53
54         public void Run() {
55             Application.Init();
56
57             ParseArgs();
58
59             _Window = new Gtk.Window("WebThing");
60             _Window.SetWmclass("webthing", "WebThing");
61             _Window.Role = "browser";
62             _Window.Destroyed += delegate { Quit(); };
63
64             WidgetGrid = new Gtk.Table(3, 3, false);
65             _Window.Add(WidgetGrid);
66
67             _ScrolledWindow = new Gtk.ScrolledWindow();
68             WidgetGrid.Attach(_ScrolledWindow, 1, 2, 1, 2);
69
70             InteriorOverlay = new Gtk.Alignment(1, 0, 0, 0);
71             WidgetGrid.Attach(InteriorOverlay, 1, 2, 1, 2);
72
73             _WebView = new WebKit.WebView();
74             _WebView.TitleChanged += delegate(object o, TitleChangedArgs e) {
75                 _Window.Title = e.Title + " - WebThing";
76             };
77             soup_settings();
78
79             _ScrolledWindow.Add(_WebView);
80
81             _Window.ShowAll();
82
83             Plugins = new Dictionary<string,WebThingPlugin>();
84             // TODO: Conf.Get("plugins") instead of hard-coded path?
85             using (TextReader f = new StreamReader("plugins.conf")) {
86                 string line;
87                 while ((line = f.ReadLine()) != null) {
88                     line = line.Trim();
89                     LoadPlugin(line);
90                 }
91             }
92
93             Application.Run();
94         }
95
96         protected void ParseArgs() {
97             Options = new Dictionary<string,string>();
98             Queue<string> q = new Queue<string>();
99             foreach (string s in System.Environment.GetCommandLineArgs()) {
100                 q.Enqueue(s);
101             }
102             q.Dequeue();   // Remove self argument
103
104             Regex SimpleOpt = new Regex(@"^-([a-zA-Z0-9]+)$");
105             Regex LongOpt   = new Regex(@"^--([\w-]+)$");
106             string OptLast = null;
107             List<string> args = new List<string>();
108
109             while (q.Count > 0) {
110                 string opt = q.Dequeue();
111                 Match m;
112                    
113                 m = SimpleOpt.Match(opt);
114                 if (m.Success) {
115                     string s = m.Groups[1].Value;
116                     if (s.Length > 1) {
117                         foreach (char c in s) {
118                             Options[c.ToString()] = "";
119                         }
120                         OptLast = null;
121                     } else {
122                         Options[s] = "";
123                         OptLast = s;
124                     }
125                     continue;
126                 }
127
128                 m = LongOpt.Match(opt);
129                 if (m.Success) {
130                     string s = m.Groups[1].Value;
131                     Options[s] = "";
132                     OptLast = s;
133                     continue;
134                 }
135
136                 // else
137
138                 if (OptLast != null) {
139                     Options[OptLast] = opt;
140                     OptLast = null;
141                 } else {
142                     args.Add(opt);
143                 }
144             }
145             Arguments = args.ToArray();
146
147             /*
148             Console.WriteLine("Options:");
149             foreach (string key in Options.Keys)
150                 Console.WriteLine("   {0}\t{1}", key, Options[key]);
151
152             Console.WriteLine("Arguments: {0}", String.Join(" ", Arguments));
153             */
154         }
155
156         public void LoadPlugin(string assemblyname) {
157             Assembly a = Assembly.LoadFile("plugins/" + assemblyname + ".dll");
158             Type[] types = a.GetTypes();
159             foreach (Type t in types) {
160                 if (t.GetInterface("WebThingPlugin") != null) {
161                     WebThingPlugin p = (WebThingPlugin) a.CreateInstance(t.FullName, false, BindingFlags.ExactBinding, null, null, null, null);
162                     p.Init(this);
163                     Plugins[t.FullName] = p;
164                     Console.WriteLine("Successfully loaded {0}", t.FullName);
165                 }
166             }
167         }
168
169         public void AttachWidget(Gtk.Widget widget, CompassDirection direction, AttachOptions xoptions, AttachOptions yoptions) {
170             switch(direction) {
171             case CompassDirection.N:
172                 WidgetGrid.Attach(widget, 0, 3, 0, 1, xoptions, yoptions, 0, 0);
173                 break;
174             case CompassDirection.E:
175                 WidgetGrid.Attach(widget, 2, 3, 1, 2, xoptions, yoptions, 0, 0);
176                 break;
177             case CompassDirection.S:
178                 WidgetGrid.Attach(widget, 0, 3, 2, 3, xoptions, yoptions, 0, 0);
179                 break;
180             case CompassDirection.W:
181                 WidgetGrid.Attach(widget, 0, 1, 1, 2, xoptions, yoptions, 0, 0);
182                 break;
183             case CompassDirection.Interior:
184                 InteriorOverlay.Add(widget);
185                 break;
186             }
187         }
188
189         public void AttachWidget(Gtk.Widget widget, CompassDirection direction) {
190             AttachWidget(widget, direction, 0, 0);
191         }
192
193         public void OpenUri(string Uri) {
194             if (!Regex.IsMatch(Uri, @"://")) {
195                 Uri = String.Format("http://{0}", Uri);
196             }
197             wv.Open(Uri);
198         }
199
200         public void Quit() {
201             // TODO: Create a way of shutting down plugins
202             Application.Quit();
203         }
204     }
205 }