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, NE, E, SE, S, SW, W, NW,
- Interior
- }
-
- public class WebThing {
- public Gtk.Window Window {
- get { return _Window; }
- }
-
- public Gtk.Window w {
- get { return _Window; }
- }
-
- public Gtk.ScrolledWindow ScrolledWindow {
- get { return _ScrolledWindow; }
- }
-
- public Gtk.ScrolledWindow sw {
- get { return _ScrolledWindow; }
- }
-
- public WebKit.WebView WebView {
- get { return _WebView; }
- }
-
- public WebKit.WebView wv {
- get { return _WebView; }
- }
-
- private Gtk.Window _Window;
- private ScrolledWindow _ScrolledWindow;
- private WebKit.WebView _WebView;
- private Gtk.Table WidgetGrid;
- private Gtk.Alignment InteriorOverlay;
-
- public Dictionary<string,object> Plugins;
-
- public void Run() {
- Application.Init();
- _Window = new Gtk.Window("WebThing");
- _Window.Destroyed += delegate { Application.Quit(); };
-
- WidgetGrid = new Gtk.Table(3, 3, false);
- _Window.Add(WidgetGrid);
-
- _ScrolledWindow = new Gtk.ScrolledWindow();
- WidgetGrid.Attach(_ScrolledWindow, 1, 2, 1, 2);
-
- InteriorOverlay = new Gtk.Alignment(1, 0, 0, 0);
- WidgetGrid.Attach(InteriorOverlay, 1, 2, 1, 2);
-
- _WebView = new WebKit.WebView();
- _WebView.TitleChanged += delegate(object o, TitleChangedArgs e) {
- _Window.Title = e.Title + " - WebThing";
- };
- _ScrolledWindow.Add(_WebView);
-
- _Window.ShowAll();
-
- Plugins = new Dictionary<string, object>();
- // 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);
- }
- }
-
- Application.Run();
- }
-
- public void LoadPlugin(string assemblyname) {
- Assembly a = Assembly.LoadFile("plugins/" + assemblyname + ".dll");
- object obj = a.CreateInstance("Plugin", false, BindingFlags.ExactBinding, null, new object[] { this }, null, null);
- Plugins[assemblyname] = obj;
- }
-
- public void AttachWidget(Gtk.Widget widget, CompassDirection direction, AttachOptions xoptions, AttachOptions yoptions) {
- switch(direction) {
- case CompassDirection.N:
- WidgetGrid.Attach(widget, 1, 2, 0, 1, xoptions, yoptions, 0, 0);
- break;
- case CompassDirection.NE:
- WidgetGrid.Attach(widget, 2, 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.SE:
- WidgetGrid.Attach(widget, 2, 3, 2, 3, xoptions, yoptions, 0, 0);
- break;
- case CompassDirection.S:
- WidgetGrid.Attach(widget, 1, 2, 2, 3, xoptions, yoptions, 0, 0);
- break;
- case CompassDirection.SW:
- WidgetGrid.Attach(widget, 0, 1, 2, 3, xoptions, yoptions, 0, 0);
- break;
- case CompassDirection.W:
- WidgetGrid.Attach(widget, 0, 1, 1, 2, xoptions, yoptions, 0, 0);
- break;
- case CompassDirection.NW:
- WidgetGrid.Attach(widget, 0, 1, 0, 1, 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 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);
+ }
+ }
}