using System; using System.Collections.Generic; using System.IO; using System.Text.RegularExpressions; using System.Runtime.InteropServices; using Gtk; using GtkSharp; using WebKit; namespace bytex64.WebThing { public enum AttachPoint { 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 Gtk.Table WidgetGrid; private Gtk.Alignment InteriorOverlay; public PluginManager Plugins; public SearchHandler Search; [DllImport ("SoupSettings.dll")] private static extern void soup_settings(); // Main setup public void Run() { Application.Init(); soup_settings(); Config.ParseCommandLine(); Config.Load(); //Config.DumpOptions(); // Initialize Window _Window = new Gtk.Window("WebThing"); // The GTK+ docs say not to use this, but the defaults are // based on the executable name, which I don't like. _Window.SetWmclass("webthing", "WebThing"); _Window.Role = "browser"; { int w, h; if (Config.Options.ContainsKey("Width")) w = Convert.ToInt32(Config.Options["Width"]); else w = 640; if (Config.Options.ContainsKey("Height")) h = Convert.ToInt32(Config.Options["Height"]); else h = 480; _Window.DefaultSize = new Gdk.Size(w, h); } _Window.Destroyed += delegate { Quit(); }; // Initialize WidgetGrid // The WidgetGrid holds the Tabs (and thus WebKit) and // AttachPoint.Interior in the center, and allows widgets to // be added on the sides of the browser WidgetGrid = new Gtk.Table(3, 3, false); _Window.Add(WidgetGrid); // Initialize Tabs // Tabs are a core feature of WebThing, not a plugin. By // default, they do nothing -- Tab manipulation is left to // plugins to define. _Tabs = new Gtk.Notebook(); _Tabs.ShowBorder = false; _Tabs.Scrollable = true; _Tabs.SwitchPage += Tabs_SwitchPage; WidgetGrid.Attach(_Tabs, 1, 2, 1, 2); // InteriorOverlay goes over top of the Tabs to contain // widgets that hover over the content, like progress, or // inline search. This is not a very solid idea ATM. InteriorOverlay = new Gtk.Alignment(1, 0, 0, 0); WidgetGrid.Attach(InteriorOverlay, 1, 2, 1, 2); _Window.ShowAll(); // Load Plugins Plugins = new PluginManager(this); Plugins.Load(); // Load Search Handlers Search = new SearchHandler(this); // Create a new, default WebThingView if one has not already // been created. if (Tabs.NPages == 0) OpenTab("http://dominionofawesome.com/"); WebView.GrabFocus(); Application.Run(); } public void Quit() { Plugins.Deinit(); Application.Quit(); } // Widget attachment public void AttachWidget(Gtk.Widget widget, AttachPoint direction, AttachOptions xoptions, AttachOptions yoptions) { switch(direction) { case AttachPoint.N: WidgetGrid.Attach(widget, 0, 3, 0, 1, xoptions, yoptions, 0, 0); break; case AttachPoint.E: WidgetGrid.Attach(widget, 2, 3, 1, 2, xoptions, yoptions, 0, 0); break; case AttachPoint.S: WidgetGrid.Attach(widget, 0, 3, 2, 3, xoptions, yoptions, 0, 0); break; case AttachPoint.W: WidgetGrid.Attach(widget, 0, 1, 1, 2, xoptions, yoptions, 0, 0); break; case AttachPoint.Interior: InteriorOverlay.Add(widget); break; } } public void AttachWidget(Gtk.Widget widget, AttachPoint direction) { AttachWidget(widget, direction, 0, 0); } // Tab management public WebThingView NewTab() { WebThingView newview = NewWebThingView(); Plugins.WebViewSetup(newview.WebView); return newview; } 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; } 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) { Console.WriteLine("Attempted to close tab out of range: {0}", tab); } } } private void Tabs_SwitchPage(object o, SwitchPageArgs e) { Gtk.Widget page = _Tabs.GetNthPage((int)e.PageNum); _Window.Title = _Tabs.GetTabLabelText(page) + " - WebThing"; } // Uri loading private string GetUri(string query) { Uri u; try { u = new Uri(query); return u.ToString(); } catch(UriFormatException) { try { u = new Uri(String.Format("http://{0}", query)); return u.ToString(); } catch (UriFormatException) { return Search.Transform(query); } } } public bool Open(string query) { string uri = GetUri(query); if (uri == null) return false; wv.Open(uri); return true; } public bool OpenTab(string query) { WebThingView wtv = NewTab(); string uri = GetUri(query); if (uri == null) return false; wtv.WebView.Open(uri); return true; } public void Scroll(double x, double y) { ScrolledWindow.Hadjustment.Value += x; if (ScrolledWindow.Hadjustment.Value > ScrolledWindow.Hadjustment.Upper - ScrolledWindow.Hadjustment.PageSize) ScrolledWindow.Hadjustment.Value = ScrolledWindow.Hadjustment.Upper - ScrolledWindow.Hadjustment.PageSize; ScrolledWindow.Vadjustment.Value += y; if (ScrolledWindow.Vadjustment.Value > ScrolledWindow.Vadjustment.Upper - ScrolledWindow.Vadjustment.PageSize) ScrolledWindow.Vadjustment.Value = ScrolledWindow.Vadjustment.Upper - ScrolledWindow.Vadjustment.PageSize; } public void Bump(int x, int y) { Scroll(x * ScrolledWindow.Hadjustment.StepIncrement, y * ScrolledWindow.Vadjustment.StepIncrement); } } }