Added tabs
authorChip Black <bytex64@bytex64.net>
Thu, 4 Jun 2009 20:26:58 +0000 (15:26 -0500)
committerChip Black <bytex64@bytex64.net>
Thu, 4 Jun 2009 20:31:07 +0000 (15:31 -0500)
Quite a bit has been reworked.  The WebView is now part of a
WebThingView container which integrates the scrollbars.  Tab
initialization has been split into two pieces, one for creating the
tab, and another for running plugins on it.

Also, for some reason I forgot to add WebThingPlugin.cs last time.
Whoops.

Makefile
WebThing.cs
WebThingPlugin.cs [new file with mode: 0644]
WebThingView.cs [new file with mode: 0644]
plugins/DefaultPage.cs
plugins/FFNav.cs
plugins/LoadProgress.cs
plugins/Vimish.cs

index afeea07..1fbd2b8 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ all: main.exe plugins
 main.exe: main.cs WebThing.dll SoupSettings.so
        gmcs $(CSFLAGS) -r:WebThing.dll main.cs
 
-WebThing.dll: WebThing.cs WebThingPlugin.cs
+WebThing.dll: WebThing.cs WebThingView.cs WebThingPlugin.cs
        gmcs $(CSFLAGS) $(references) -target:library -out:$@ $^
 
 SoupSettings.so: SoupSettings.c
index 523a160..7855ae3 100644 (file)
@@ -14,33 +14,56 @@ namespace bytex64.WebThing {
     }
 
     public class WebThing {
+        private Gtk.Window _Window;
         public Gtk.Window Window {
             get { return _Window; }
         }
-
         public Gtk.Window w {
             get { return _Window; }
         }
 
-        public Gtk.ScrolledWindow ScrolledWindow {
-            get { return _ScrolledWindow; }
+        public ScrolledWindow ScrolledWindow {
+            get { return Tabs.CurrentPageWidget as ScrolledWindow; }
         }
-
-        public Gtk.ScrolledWindow sw {
-            get { return _ScrolledWindow; }
+        public ScrolledWindow sw {
+            get { return ScrolledWindow; }
         }
 
-        public WebKit.WebView WebView {
-            get { return _WebView; }
+        public WebView WebView {
+            get { return (Tabs.CurrentPageWidget as WebThingView).WebView; }
+        }
+        public WebView wv {
+            get { return WebView; }
         }
 
-        public WebKit.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.Window _Window;
-        private ScrolledWindow _ScrolledWindow;
-        private WebKit.WebView _WebView;
         private Gtk.Table WidgetGrid;
         private Gtk.Alignment InteriorOverlay;
 
@@ -53,9 +76,11 @@ namespace bytex64.WebThing {
 
         public void Run() {
             Application.Init();
-
+            Plugins = new Dictionary<string,WebThingPlugin>();
             ParseArgs();
 
+            soup_settings();
+
             _Window = new Gtk.Window("WebThing");
             _Window.SetWmclass("webthing", "WebThing");
             _Window.Role = "browser";
@@ -64,23 +89,17 @@ namespace bytex64.WebThing {
             WidgetGrid = new Gtk.Table(3, 3, false);
             _Window.Add(WidgetGrid);
 
-            _ScrolledWindow = new Gtk.ScrolledWindow();
-            WidgetGrid.Attach(_ScrolledWindow, 1, 2, 1, 2);
+            _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);
 
-            _WebView = new WebKit.WebView();
-            _WebView.TitleChanged += delegate(object o, TitleChangedArgs e) {
-                _Window.Title = e.Title + " - WebThing";
-            };
-            soup_settings();
-
-            _ScrolledWindow.Add(_WebView);
-
             _Window.ShowAll();
 
-            Plugins = new Dictionary<string,WebThingPlugin>();
+            WebThingView newview = NewWebThingView();
+
             // TODO: Conf.Get("plugins") instead of hard-coded path?
             using (TextReader f = new StreamReader("plugins.conf")) {
                 string line;
@@ -90,6 +109,9 @@ namespace bytex64.WebThing {
                 }
             }
 
+            WebViewSetupPlugins(newview.WebView);
+            newview.WebView.GrabFocus();
+
             Application.Run();
         }
 
@@ -157,7 +179,7 @@ namespace bytex64.WebThing {
             Assembly a = Assembly.LoadFile("plugins/" + assemblyname + ".dll");
             Type[] types = a.GetTypes();
             foreach (Type t in types) {
-                if (t.GetInterface("WebThingPlugin") != null) {
+                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;
@@ -190,16 +212,69 @@ namespace bytex64.WebThing {
             AttachWidget(widget, direction, 0, 0);
         }
 
-        public void OpenUri(string Uri) {
+        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, @"://")) {
-                Uri = String.Format("http://{0}", Uri);
+                return String.Format("http://{0}", Uri);
             }
-            wv.Open(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";
+        }
     }
 }
diff --git a/WebThingPlugin.cs b/WebThingPlugin.cs
new file mode 100644 (file)
index 0000000..91c68ca
--- /dev/null
@@ -0,0 +1,8 @@
+using WebKit;
+
+namespace bytex64.WebThing {
+    public abstract class WebThingPlugin {
+        public abstract void Init(WebThing wt);
+        public virtual void InitWebView(WebView wv) {}
+    }
+}
diff --git a/WebThingView.cs b/WebThingView.cs
new file mode 100644 (file)
index 0000000..f58ca36
--- /dev/null
@@ -0,0 +1,17 @@
+using WebKit;
+using Gtk;
+
+namespace bytex64.WebThing {
+    public class WebThingView : ScrolledWindow {
+        private WebView _WebView;
+        public WebView WebView {
+            get { return _WebView; }
+        }
+
+        public WebThingView() {
+            _WebView = new WebView();
+            Add(_WebView);
+            _WebView.Show();
+        }
+    }
+}
index 38ed672..e0f65d6 100644 (file)
@@ -2,7 +2,7 @@ using System;
 using bytex64.WebThing;
 
 public class DefaultPage : WebThingPlugin {
-    public void Init(WebThing wt) {
+    public override void Init(WebThing wt) {
         if (wt.Arguments.Length > 0) {
             wt.OpenUri(wt.Arguments[0]);
         } else {
index f8ba39c..4869c2f 100644 (file)
@@ -1,29 +1,56 @@
 using System;
 using Gtk;
+using WebKit;
 using bytex64.WebThing;
 
 public class FFNav : WebThingPlugin {
     WebThing wt;
 
-    public void Init(WebThing wt) {
+    public override void Init(WebThing wt) {
         this.wt = wt;
-        wt.WebView.KeyPressEvent += WebView_KeyPress;
+    }
+
+    public override void InitWebView(WebView wv) {
+        wv.KeyPressEvent += WebView_KeyPress;
     }
 
     private void WebView_KeyPress(object o, KeyPressEventArgs e) {
+        WebView wv = (WebView) o;
         if ((e.Event.State & Gdk.ModifierType.Mod1Mask) != 0) {
             switch(e.Event.Key) {
             case Gdk.Key.Left:
-                wt.WebView.GoBack();
+                wv.GoBack();
                 break;
             case Gdk.Key.Right:
-                wt.WebView.GoForward();
+                wv.GoForward();
+                break;
+            }
+        } else if ((e.Event.State & Gdk.ModifierType.ControlMask) != 0) {
+            switch(e.Event.Key) {
+            case Gdk.Key.t:
+                wt.NewTab();
+                wt.Tabs.CurrentPage = wt.Tabs.NPages - 1;
+                break;
+            case Gdk.Key.w:
+                wt.CloseTab();
+                break;
+            case Gdk.Key.ISO_Left_Tab:
+                if (wt.Tabs.CurrentPage == 0)
+                    wt.Tabs.CurrentPage = wt.Tabs.NPages - 1;
+                else
+                    wt.Tabs.PrevPage();
+                break;
+            case Gdk.Key.Tab:
+                if (wt.Tabs.CurrentPage == wt.Tabs.NPages - 1)
+                    wt.Tabs.CurrentPage = 0;
+                else
+                    wt.Tabs.NextPage();
                 break;
             }
         } else {
             switch(e.Event.Key) {
             case Gdk.Key.BackSpace:
-                wt.WebView.GoBack();
+                wv.GoBack();
                 break;
             }
         }
index a4be542..08ffbf6 100644 (file)
@@ -16,14 +16,16 @@ public class LoadThrobber : Gtk.DrawingArea {
     public LoadThrobber(WebThing wt) {
         LoadState = Mode.LoadStarted;
 
-        wt.WebView.LoadStarted += WebView_LoadStarted;
-        wt.WebView.LoadCommitted += WebView_LoadCommitted;
-        wt.WebView.LoadProgressChanged += WebView_LoadProgressChanged;
-        wt.WebView.LoadFinished += WebView_LoadFinished;
-
         SetSizeRequest(64, 64);
     }
 
+    public void AttachSignals(WebView wv) {
+        wv.LoadStarted += WebView_LoadStarted;
+        wv.LoadCommitted += WebView_LoadCommitted;
+        wv.LoadProgressChanged += WebView_LoadProgressChanged;
+        wv.LoadFinished += WebView_LoadFinished;
+    }
+
     protected override bool OnExposeEvent(Gdk.EventExpose e) {
         Gdk.Window w = e.Window;
         Gdk.GC gc = new Gdk.GC(w);
@@ -80,8 +82,14 @@ public class LoadThrobber : Gtk.DrawingArea {
 }
 
 public class LoadThrobberPlugin : WebThingPlugin {
-    public void Init(WebThing wt) {
-        LoadThrobber lt = new LoadThrobber(wt);
+    LoadThrobber lt;
+
+    public override void Init(WebThing wt) {
+        lt = new LoadThrobber(wt);
         wt.AttachWidget(lt, CompassDirection.Interior);
     }
+
+    public override void InitWebView(WebView wv) {
+        lt.AttachSignals(wv);
+    }
 }
index 7acdad2..8de862a 100644 (file)
@@ -1,15 +1,17 @@
 using System;
 using System.Text.RegularExpressions;
 using Gtk;
+using WebKit;
 using bytex64.WebThing;
 
 public class Vimish : WebThingPlugin {
     WebThing wt;
     Gtk.Entry commandline;
 
-    public void Init(WebThing wt) {
+    public override void Init(WebThing wt) {
         this.wt = wt;
-        wt.WebView.KeyPressEvent += WebView_KeyPress;
+
+        wt.Window.KeyPressEvent += Window_KeyPress;
 
         commandline = new Gtk.Entry();
         commandline.Activated += command_Activate;
@@ -19,36 +21,56 @@ public class Vimish : WebThingPlugin {
         commandline.Hide();
     }
 
-    private void WebView_KeyPress(object o, KeyPressEventArgs e) {
-        Console.WriteLine(e.Event.Key);
+    public override void InitWebView(WebView wv) {
+        wv.KeyPressEvent += WebView_KeyPress;
+    }
+
+    private void Window_KeyPress(object o, KeyPressEventArgs e) {
         switch(e.Event.Key) {
-        case Gdk.Key.j:
-            wt.ScrolledWindow.Vadjustment.Value += wt.ScrolledWindow.Vadjustment.StepIncrement;
-            break;
-        case Gdk.Key.k:
-            wt.ScrolledWindow.Vadjustment.Value -= wt.ScrolledWindow.Vadjustment.StepIncrement;
-            break;
-        case Gdk.Key.l:
-            wt.ScrolledWindow.Hadjustment.Value += wt.ScrolledWindow.Hadjustment.StepIncrement;
-            break;
-        case Gdk.Key.h:
-            wt.ScrolledWindow.Hadjustment.Value -= wt.ScrolledWindow.Hadjustment.StepIncrement;
-            break;
         case Gdk.Key.o:
             CommandStart("open ");
             break;
-        case Gdk.Key.r:
-            wt.WebView.Reload();
-            break;
         case Gdk.Key.t:
             CommandStart("tabopen ");
             break;
         case Gdk.Key.colon:
             CommandlineShow();
             break;
-        case Gdk.Key.Escape:
-            wt.WebView.ExecuteScript("document.activeElement.blur()");
-            break;
+        }
+    }
+
+    private void WebView_KeyPress(object o, KeyPressEventArgs e) {
+        Console.WriteLine(e.Event.Key);
+        if ((Gdk.ModifierType.ControlMask & e.Event.State) != 0) {
+            switch(e.Event.Key) {
+            case Gdk.Key.n:
+                wt.Tabs.NextPage();
+                break;
+            case Gdk.Key.p:
+                wt.Tabs.PrevPage();
+                break;
+            }
+        } else {
+            switch(e.Event.Key) {
+            case Gdk.Key.j:
+                wt.ScrolledWindow.Vadjustment.Value += wt.ScrolledWindow.Vadjustment.StepIncrement;
+                break;
+            case Gdk.Key.k:
+                wt.ScrolledWindow.Vadjustment.Value -= wt.ScrolledWindow.Vadjustment.StepIncrement;
+                break;
+            case Gdk.Key.l:
+                wt.ScrolledWindow.Hadjustment.Value += wt.ScrolledWindow.Hadjustment.StepIncrement;
+                break;
+            case Gdk.Key.h:
+                wt.ScrolledWindow.Hadjustment.Value -= wt.ScrolledWindow.Hadjustment.StepIncrement;
+                break;
+            case Gdk.Key.r:
+                wt.WebView.Reload();
+                break;
+            case Gdk.Key.Escape:
+                wt.WebView.ExecuteScript("document.activeElement.blur()");
+                break;
+            }
         }
     }
 
@@ -72,10 +94,24 @@ public class Vimish : WebThingPlugin {
     private void command_Activate(object o, EventArgs e) {
         string[] args = Regex.Split(commandline.Text, @"\s+");
         switch(args[0]) {
+        case "close":
+            wt.CloseTab();
+            break;
         case "open":
             if (args.Length < 2) return;
             wt.OpenUri(args[1]);
             break;
+        case "tabopen":
+            if (args.Length < 2) return;
+            wt.OpenUriTab(args[1]);
+            wt.Tabs.CurrentPage = wt.Tabs.NPages - 1;
+            break;
+        case "n":
+            wt.Tabs.NextPage();
+            break;
+        case "p":
+            wt.Tabs.PrevPage();
+            break;
         case "q":
             wt.Quit();
             break;