Thumbnail file hits. Based on a patch from D Bera
[beagle.git] / Tiles / TileCanvas.cs
blob82e68ff4cfc94afc42ca600abed899c36a4f6991
1 //
2 // TileCanvas.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a
9 // copy of this software and associated documentation files (the "Software"),
10 // to deal in the Software without restriction, including without limitation
11 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 // and/or sell copies of the Software, and to permit persons to whom the
13 // Software is furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 // DEALINGS IN THE SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.Diagnostics;
30 using System.Reflection;
31 using System.IO;
32 using System.Text;
33 using Beagle.Util;
34 using Gecko;
36 namespace Beagle.Tile {
38 public class TileCanvas : Gecko.WebControl {
40 public event EventHandler PreRenderEvent;
41 public event EventHandler PostRenderEvent;
43 public TileCanvas () : base ()
45 OpenUri += OnOpenUri;
48 private void DispatchAction (string tile_id,
49 string action)
51 Tile t = GetTile (tile_id);
53 if (t == null)
54 return;
57 MethodInfo info = t.GetType().GetMethod (action,
58 BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
59 null,
60 CallingConventions.Any,
61 new Type[] {},
62 null);
63 if (info == null) {
64 Console.WriteLine ("Couldn't find method called {0}", action);
65 return;
67 object[] attrs = info.GetCustomAttributes (false);
68 foreach (object attr in attrs) {
69 if (attr is TileActionAttribute) {
70 info.Invoke (t, null);
71 return;
74 Console.WriteLine ("{0} does not have the TileAction attribute");
77 private void OnOpenUri (object o, OpenUriArgs args)
79 string uri = args.AURI;
80 System.Console.WriteLine ("Open URI: {0}", uri);
82 args.RetVal = true;
84 if (DoAction (uri))
85 return;
87 if (uri.StartsWith ("action:")) {
88 int pos1 = "action:".Length;
89 int pos2 = uri.IndexOf ("!");
90 if (pos2 > 0) {
91 string tile_id = uri.Substring (pos1, pos2 - pos1);
92 string action = uri.Substring (pos2 + 1);
93 DispatchAction (tile_id, action);
97 string command = null;
98 string commandArgs = null;
100 if (uri.StartsWith (Uri.UriSchemeHttp)
101 || uri.StartsWith (Uri.UriSchemeHttps)
102 || uri.StartsWith (Uri.UriSchemeFile)) {
103 command = "gnome-open";
104 commandArgs = "'" + uri + "'";
105 } else if (uri.StartsWith (Uri.UriSchemeMailto)) {
106 command = "evolution";
107 commandArgs = uri;
110 if (command != null) {
111 Process p = new Process ();
112 p.StartInfo.UseShellExecute = false;
113 p.StartInfo.FileName = command;
114 if (args != null)
115 p.StartInfo.Arguments = commandArgs;
116 try {
117 p.Start ();
118 } catch (Exception e) {
119 Console.WriteLine ("Unable to run {0}: {1}", command, e);
121 return;
125 return;
128 /////////////////////////////////////////////////
130 Tile root = null;
132 public Tile Root {
133 get { return root; }
134 set {
135 root = value;
136 root.SetChangedHandler (new TileChangedHandler (OnTileChanged));
137 Render ();
141 /////////////////////////////////////////////////
143 Hashtable actionTable = null;
144 int actionId = 1;
146 private void ClearActions ()
148 actionTable = new Hashtable ();
149 actionId = 1;
152 private string AddAction (TileActionHandler handler)
154 if (handler == null)
155 return "dynaction:NULL";
156 string key = "dynaction:" + actionId.ToString ();
157 ++actionId;
158 actionTable [key] = handler;
159 return key;
162 private bool DoAction (string key)
164 TileActionHandler handler = (TileActionHandler) actionTable [key];
165 if (handler != null) {
166 handler ();
167 return true;
169 return false;
172 /////////////////////////////////////////////////
174 Hashtable tileTable = null;
176 private void ClearTiles ()
178 tileTable = new Hashtable ();
181 private void CacheTile (Tile tile)
183 tileTable [tile.UniqueKey] = tile;
184 tile.SetChangedHandler (new TileChangedHandler (OnTileChanged));
187 private Tile GetTile (string key)
189 if (key == "")
190 return root;
191 return (Tile) tileTable [key];
194 /////////////////////////////////////////////////
196 private class TileCanvasRenderContext : TileRenderContext {
198 TileCanvas canvas;
199 Tile tileMain;
201 public TileCanvasRenderContext (TileCanvas _canvas, Tile _tile)
203 canvas = _canvas;
204 tileMain = _tile;
205 canvas.CacheTile (tileMain);
208 override public void Write (string markup)
210 canvas.AppendData (markup);
213 override public void Link (string label,
214 TileActionHandler handler)
216 string key = canvas.AddAction (handler);
217 Write ("<a href=\"{0}\">{1}</a>", key, label);
220 override public void Tile (Tile tile)
222 canvas.CacheTile (tile);
223 tile.Render (this);
227 private static ArrayList style_attributes = null;
228 private static ArrayList style_templates = null;
229 private static string preferred_font_family;
230 private static double preferred_font_size;
232 static private void GetFontSettings ()
234 GConf.Client client = new GConf.Client ();
235 string font = null;
237 try {
238 font = client.Get ("/desktop/gnome/interface/font_name") as string;
239 } catch (GConf.NoSuchKeyException) { }
241 // Sans 10 seems to be the default GNOME fallback
242 if (font == null)
243 font = "Sans 10";
245 Pango.FontDescription font_desc = Pango.FontDescription.FromString (font);
247 preferred_font_family = font_desc.Family;
248 preferred_font_size = font_desc.Size / Pango.Scale.PangoScale;
251 static private void ScanAssembly (Assembly assembly)
253 style_attributes = new ArrayList ();
254 foreach (Type type in assembly.GetTypes ()) {
255 if (type.IsSubclassOf (typeof (Tile))) {
256 foreach (object obj in Attribute.GetCustomAttributes (type)) {
257 if (obj is TileStyleAttribute) {
258 style_attributes.Add (obj);
265 private void RenderStyles (TileRenderContext ctx)
267 if (style_attributes == null)
268 ScanAssembly (Assembly.GetExecutingAssembly ());
270 if (style_templates == null) {
271 GetFontSettings ();
273 style_templates = new ArrayList ();
274 foreach (TileStyleAttribute attr in style_attributes) {
275 Template t = new Template (attr.Resource);
276 t["FontFamily"] = preferred_font_family;
277 t["FontSize"] = preferred_font_size.ToString ();
278 style_templates.Add (t);
282 foreach (Template t in style_templates) {
283 ctx.Write (t.ToString ());
287 private void PaintTile (Tile tile)
289 TileCanvasRenderContext ctx;
290 ctx = new TileCanvasRenderContext (this,
291 tile);
293 // IMPORTANT! The <meta> tag has to be in the first
294 // chunk written to the stream or else the encoding
295 // will be wrong!
296 ctx.Write ("<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n");
298 ctx.Write ("<style type=\"text/css\" media=\"screen\">\n");
299 RenderStyles (ctx);
300 ctx.Write ("</style>\n");
302 ctx.Write ("</head>\n");
304 if (tile != null) {
305 tile.Render (ctx);
308 ctx.Write ("</html>");
311 /////////////////////////////////////////////////
313 StringBuilder content;
315 public String Source {
316 get { return content.ToString (); }
319 public new void AppendData (string data)
321 content.Append (data);
324 /////////////////////////////////////////////////
326 private void DoRender ()
328 if (time == null) {
329 time = new Beagle.Util.Stopwatch ();
330 time.Start ();
332 System.Console.WriteLine ("Rendering");
333 if (PreRenderEvent != null)
334 PreRenderEvent (this, new EventArgs ());
336 ClearActions ();
337 ClearTiles ();
339 string mime_type = "text/html";
340 if (Environment.GetEnvironmentVariable ("BEST_DEBUG_HTML") != null)
341 mime_type = "text/plain";
343 content = new StringBuilder ();
344 PaintTile (root);
345 RenderData (content.ToString (), "file:///", mime_type);
347 if (PostRenderEvent != null)
348 PostRenderEvent (this, new EventArgs ());
350 time.Stop ();
351 System.Console.WriteLine ("Done Rendering: {0}",
352 time);
353 time = null;
358 /////////////////////////////////////////////////
360 private uint renderId = 0;
362 public void Render ()
364 lock (this) {
365 if (renderId != 0) {
366 GLib.Source.Remove (renderId);
367 renderId = 0;
369 DoRender ();
373 private bool RenderHandler ()
375 lock (this) {
376 renderId = 0;
377 DoRender ();
379 return false;
382 Beagle.Util.Stopwatch time;
383 public void ScheduleRender ()
385 time = new Beagle.Util.Stopwatch ();
386 time.Start ();
387 lock (this) {
388 if (renderId != 0)
389 return;
390 renderId = GLib.Idle.Add (new GLib.IdleHandler (RenderHandler));
394 private void OnTileChanged (Tile tile)
396 ScheduleRender ();