Flesh out life cycle of a plugin
[WebThing.git] / WebThing.cs
1 using System;
2 using System.Collections.Generic;
3 using System.IO;
4 using System.Text.RegularExpressions;
5 using System.Runtime.InteropServices;
6 using Gtk;
7 using GtkSharp;
8 using WebKit;
9
10 namespace bytex64.WebThing {
11     public enum AttachPoint {
12         N, E, S, W, Interior
13     }
14
15     public class WebThing {
16         private Gtk.Window _Window;
17         public Gtk.Window Window {
18             get { return _Window; }
19         }
20         public Gtk.Window w {
21             get { return _Window; }
22         }
23
24         public ScrolledWindow ScrolledWindow {
25             get { return Tabs.CurrentPageWidget as ScrolledWindow; }
26         }
27         public ScrolledWindow sw {
28             get { return ScrolledWindow; }
29         }
30
31         public WebView WebView {
32             get { return (Tabs.CurrentPageWidget as WebThingView).WebView; }
33         }
34         public WebView wv {
35             get { return WebView; }
36         }
37
38         private Gtk.Notebook _Tabs;
39         public Gtk.Notebook Tabs {
40             get { return _Tabs; }
41         }
42
43         private Gtk.Table WidgetGrid;
44         private Gtk.Alignment InteriorOverlay;
45
46         public PluginManager Plugins;
47
48         [DllImport ("SoupSettings.dll")]
49         private static extern void soup_settings();
50
51         // Main setup
52         public void Run() {
53             Application.Init();
54
55             soup_settings();
56
57             Config.ParseCommandLine();
58             Config.Load();
59             //Config.DumpOptions();
60
61             // Initialize Window
62             _Window = new Gtk.Window("WebThing");
63             // The GTK+ docs say not to use this, but the defaults are
64             // based on the executable name, which I don't like.
65             _Window.SetWmclass("webthing", "WebThing");  
66             _Window.Role = "browser";
67             _Window.Destroyed += delegate { Quit(); };
68
69             // Initialize WidgetGrid
70             // The WidgetGrid holds the Tabs (and thus WebKit) and
71             // AttachPoint.Interior in the center, and allows widgets to
72             // be added on the sides of the browser
73             WidgetGrid = new Gtk.Table(3, 3, false);
74             _Window.Add(WidgetGrid);
75
76             // Initialize Tabs
77             // Tabs are a core feature of WebThing, not a plugin.  By
78             // default, they do nothing -- Tab manipulation is left to
79             // plugins to define.
80             _Tabs = new Gtk.Notebook();
81             _Tabs.ShowBorder = false;
82             _Tabs.Scrollable = true;
83             _Tabs.SwitchPage += Tabs_SwitchPage;
84             WidgetGrid.Attach(_Tabs, 1, 2, 1, 2);
85
86             // InteriorOverlay goes over top of the Tabs to contain
87             // widgets that hover over the content, like progress, or
88             // inline search.  This is not a very solid idea ATM.
89             InteriorOverlay = new Gtk.Alignment(1, 0, 0, 0);
90             WidgetGrid.Attach(InteriorOverlay, 1, 2, 1, 2);
91
92             _Window.ShowAll();
93
94             // Load Plugins
95             Plugins = new PluginManager(this);
96             Plugins.Load();
97
98             // Create a new, default WebThingView if one has not already
99             // been created.
100             if (Tabs.NPages == 0)
101                 OpenUriTab("http://dominionofawesome.com/");
102             WebView.GrabFocus();
103
104             Application.Run();
105         }
106
107         public void Quit() {
108             // TODO: Create a way of shutting down plugins
109             Application.Quit();
110         }
111
112         // Widget attachment
113         public void AttachWidget(Gtk.Widget widget, AttachPoint direction, AttachOptions xoptions, AttachOptions yoptions) {
114             switch(direction) {
115             case AttachPoint.N:
116                 WidgetGrid.Attach(widget, 0, 3, 0, 1, xoptions, yoptions, 0, 0);
117                 break;
118             case AttachPoint.E:
119                 WidgetGrid.Attach(widget, 2, 3, 1, 2, xoptions, yoptions, 0, 0);
120                 break;
121             case AttachPoint.S:
122                 WidgetGrid.Attach(widget, 0, 3, 2, 3, xoptions, yoptions, 0, 0);
123                 break;
124             case AttachPoint.W:
125                 WidgetGrid.Attach(widget, 0, 1, 1, 2, xoptions, yoptions, 0, 0);
126                 break;
127             case AttachPoint.Interior:
128                 InteriorOverlay.Add(widget);
129                 break;
130             }
131         }
132
133         public void AttachWidget(Gtk.Widget widget, AttachPoint direction) {
134             AttachWidget(widget, direction, 0, 0);
135         }
136
137         // Tab management
138         public WebThingView NewTab() {
139             WebThingView newview = NewWebThingView();
140             Plugins.WebViewSetup(newview.WebView);
141             return newview;
142         }
143
144         private WebThingView NewWebThingView() {
145             WebThingView newview = new WebThingView();
146             Tabs.AppendPage(newview, new Label("Blank"));
147             newview.WebView.TitleChanged += delegate(object o, TitleChangedArgs e) {
148                 Tabs.SetTabLabelText((Gtk.Widget) newview, e.Title);
149                 if (newview == Tabs.CurrentPageWidget)
150                     _Window.Title = e.Title + " - WebThing";
151             };
152             newview.Show();
153             return newview;
154         }
155
156         public void CloseTab() {
157             CloseTab(_Tabs.Page);
158         }
159
160         public void CloseTab(int tab) {
161             if (_Tabs.NPages > 1) {
162                 try {
163                     WebThingView view = _Tabs.GetNthPage(tab) as WebThingView;
164                     _Tabs.RemovePage(tab);
165                     view.Dispose();
166                 } catch (ArgumentOutOfRangeException) {
167                     Console.WriteLine("Attempted to close tab out of range: {0}", tab);
168                 }
169             }
170         }
171
172         private void Tabs_SwitchPage(object o, SwitchPageArgs e) {
173             Gtk.Widget page = _Tabs.GetNthPage((int)e.PageNum);
174             _Window.Title = _Tabs.GetTabLabelText(page) + " - WebThing";
175         }
176
177         // Uri loading
178         public string FixUri(string Uri) {
179             if (!Regex.IsMatch(Uri, @"://")) {
180                 return String.Format("http://{0}", Uri);
181             }
182             return Uri;
183         }
184
185         public void OpenUri(string Uri) {
186             wv.Open(FixUri(Uri));
187         }
188
189         public void OpenUriTab(string Uri) {
190             WebThingView wtv = NewTab();
191             wtv.WebView.Open(FixUri(Uri));
192         }
193     }
194 }