using System; using System.Collections.Generic; using System.Reflection; using System.IO; using System.Text.RegularExpressions; using System.Runtime.InteropServices; using Gtk; using GtkSharp; using WebKit; namespace bytex64.WebThing { public enum CompassDirection { N, E, S, W, Interior } public class WebThing { private Gtk.Window _Window; public Gtk.Window Window { get { return _Window; } } public Gtk.Window w { get { return _Window; } } public ScrolledWindow ScrolledWindow { get { return Tabs.CurrentPageWidget as ScrolledWindow; } } public ScrolledWindow sw { get { return ScrolledWindow; } } public WebView WebView { get { return (Tabs.CurrentPageWidget as WebThingView).WebView; } } public WebView wv { get { return WebView; } } private Gtk.Notebook _Tabs; public Gtk.Notebook Tabs { get { return _Tabs; } } /* private int _CurrentTab; public int CurrentTab { get { return _CurrentTab; } set { if (value >= _Tabs.Count) _CurrentTab = _Tabs.Count - 1; else if (value < 0) _CurrentTab = 0; else _CurrentTab = value; _WebView.Hide(); _ScrolledWindow.Remove(_WebView); _WebView = _Tabs[_CurrentTab]; _ScrolledWindow.Add(_WebView); foreach (WebView view in Tabs) Console.WriteLine(view.MainFrame.Uri); _WebView.Show(); _WebView.GrabFocus(); } } */ private Gtk.Table WidgetGrid; private Gtk.Alignment InteriorOverlay; public Dictionary Plugins; public Dictionary Options; public string[] Arguments; [DllImport ("SoupSettings.dll")] private static extern void soup_settings(); public void Run() { Application.Init(); Plugins = new Dictionary(); ParseArgs(); soup_settings(); _Window = new Gtk.Window("WebThing"); _Window.SetWmclass("webthing", "WebThing"); _Window.Role = "browser"; _Window.Destroyed += delegate { Quit(); }; WidgetGrid = new Gtk.Table(3, 3, false); _Window.Add(WidgetGrid); _Tabs = new Gtk.Notebook(); _Tabs.SwitchPage += Tabs_SwitchPage; WidgetGrid.Attach(_Tabs, 1, 2, 1, 2); InteriorOverlay = new Gtk.Alignment(1, 0, 0, 0); WidgetGrid.Attach(InteriorOverlay, 1, 2, 1, 2); _Window.ShowAll(); WebThingView newview = NewWebThingView(); // TODO: Conf.Get("plugins") instead of hard-coded path? using (TextReader f = new StreamReader("plugins.conf")) { string line; while ((line = f.ReadLine()) != null) { line = line.Trim(); LoadPlugin(line); } } WebViewSetupPlugins(newview.WebView); newview.WebView.GrabFocus(); Application.Run(); } protected void ParseArgs() { Options = new Dictionary(); Queue q = new Queue(); foreach (string s in System.Environment.GetCommandLineArgs()) { q.Enqueue(s); } q.Dequeue(); // Remove self argument Regex SimpleOpt = new Regex(@"^-([a-zA-Z0-9]+)$"); Regex LongOpt = new Regex(@"^--([\w-]+)$"); string OptLast = null; List args = new List(); while (q.Count > 0) { string opt = q.Dequeue(); Match m; m = SimpleOpt.Match(opt); if (m.Success) { string s = m.Groups[1].Value; if (s.Length > 1) { foreach (char c in s) { Options[c.ToString()] = ""; } OptLast = null; } else { Options[s] = ""; OptLast = s; } continue; } m = LongOpt.Match(opt); if (m.Success) { string s = m.Groups[1].Value; Options[s] = ""; OptLast = s; continue; } // else if (OptLast != null) { Options[OptLast] = opt; OptLast = null; } else { args.Add(opt); } } Arguments = args.ToArray(); /* Console.WriteLine("Options:"); foreach (string key in Options.Keys) Console.WriteLine(" {0}\t{1}", key, Options[key]); Console.WriteLine("Arguments: {0}", String.Join(" ", Arguments)); */ } public void LoadPlugin(string assemblyname) { Assembly a = Assembly.LoadFile("plugins/" + assemblyname + ".dll"); Type[] types = a.GetTypes(); foreach (Type t in types) { if (t.IsSubclassOf(typeof(WebThingPlugin))) { WebThingPlugin p = (WebThingPlugin) a.CreateInstance(t.FullName, false, BindingFlags.ExactBinding, null, null, null, null); p.Init(this); Plugins[t.FullName] = p; Console.WriteLine("Successfully loaded {0}", t.FullName); } } } public void AttachWidget(Gtk.Widget widget, CompassDirection direction, AttachOptions xoptions, AttachOptions yoptions) { switch(direction) { case CompassDirection.N: WidgetGrid.Attach(widget, 0, 3, 0, 1, xoptions, yoptions, 0, 0); break; case CompassDirection.E: WidgetGrid.Attach(widget, 2, 3, 1, 2, xoptions, yoptions, 0, 0); break; case CompassDirection.S: WidgetGrid.Attach(widget, 0, 3, 2, 3, xoptions, yoptions, 0, 0); break; case CompassDirection.W: WidgetGrid.Attach(widget, 0, 1, 1, 2, xoptions, yoptions, 0, 0); break; case CompassDirection.Interior: InteriorOverlay.Add(widget); break; } } public void AttachWidget(Gtk.Widget widget, CompassDirection direction) { AttachWidget(widget, direction, 0, 0); } public WebView NewTab() { WebThingView newview = NewWebThingView(); WebViewSetupPlugins(newview.WebView); return newview.WebView; } private WebThingView NewWebThingView() { WebThingView newview = new WebThingView(); Tabs.AppendPage(newview, new Label("Blank")); newview.WebView.TitleChanged += delegate(object o, TitleChangedArgs e) { Tabs.SetTabLabelText((Gtk.Widget) newview, e.Title); if (newview == Tabs.CurrentPageWidget) _Window.Title = e.Title + " - WebThing"; }; newview.Show(); return newview; } private void WebViewSetupPlugins(WebView view) { foreach (string key in Plugins.Keys) { Plugins[key].InitWebView(view); } } public void CloseTab() { CloseTab(_Tabs.Page); } public void CloseTab(int tab) { if (_Tabs.NPages > 1) { try { WebThingView view = _Tabs.GetNthPage(tab) as WebThingView; _Tabs.RemovePage(tab); view.Dispose(); } catch (ArgumentOutOfRangeException) { } } } public string FixUri(string Uri) { if (!Regex.IsMatch(Uri, @"://")) { return String.Format("http://{0}", Uri); } return Uri; } public void OpenUri(string Uri) { wv.Open(FixUri(Uri)); } public void OpenUriTab(string Uri) { WebView view = NewTab(); view.Open(FixUri(Uri)); } public void Quit() { // TODO: Create a way of shutting down plugins Application.Quit(); } private void Tabs_SwitchPage(object o, SwitchPageArgs e) { Gtk.Widget page = _Tabs.GetNthPage((int)e.PageNum); _Window.Title = _Tabs.GetTabLabelText(page) + " - WebThing"; } } }