2007-03-19 Chris Toshok <toshok@ximian.com>
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / MimeIcon.cs
blob395a1caa127da0d8146af5a95634bd652d076677
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2006 Alexander Olk
22 // Authors:
24 // Alexander Olk alex.olk@googlemail.com
27 // use
28 // public static int GetIconIndexForFile( string full_filename )
29 // public static int GetIconIndexForMimeType( string mime_type )
30 // to get the image index in MimeIconEngine.SmallIcons and MimeIconEngine.LargeIcons
32 using System;
33 using System.Reflection;
34 using System.Drawing;
35 using System.Collections;
36 using System.IO;
37 using System.Text;
38 using System.Runtime.InteropServices;
39 using System.Xml;
41 namespace System.Windows.Forms
43 internal enum MimeExtensionHandlerStatus
45 OK,
46 ERROR
49 internal enum EPlatformHandler
51 Default,
52 GNOME
55 internal class ResourceImageLoader
57 static Assembly assembly = typeof (ResourceImageLoader).Assembly;
59 static internal Bitmap Get (string name)
61 using (Stream stream = assembly.GetManifestResourceStream (name)) {
62 if (stream == null) {
63 Console.WriteLine ("Failed to read {0}", name);
64 return null;
67 return new Bitmap (stream);
72 internal class MimeIconEngine
74 public static ImageList SmallIcons = new ImageList();
75 public static ImageList LargeIcons = new ImageList();
77 private static EPlatformHandler platform = EPlatformHandler.Default;
79 internal static Hashtable MimeIconIndex = new Hashtable ();
81 private static PlatformMimeIconHandler platformMimeHandler = null;
83 private static object lock_object = new Object();
85 static MimeIconEngine ()
87 SmallIcons.ColorDepth = ColorDepth.Depth32Bit;
88 SmallIcons.TransparentColor = Color.Transparent;
89 LargeIcons.ColorDepth = ColorDepth.Depth32Bit;
90 LargeIcons.TransparentColor = Color.Transparent;
92 string session = Environment.GetEnvironmentVariable ("DESKTOP_SESSION");
94 if (session != null) {
95 session = session.ToUpper ();
97 if (session == "DEFAULT") {
98 string helper = Environment.GetEnvironmentVariable ("GNOME_DESKTOP_SESSION_ID");
100 if (helper != null)
101 session = "GNOME";
103 } else
104 session = String.Empty;
106 if (Mime.MimeAvailable && session == "GNOME") {
107 SmallIcons.ImageSize = new Size (24, 24);
108 LargeIcons.ImageSize = new Size (48, 48);
110 platformMimeHandler = new GnomeHandler ();
111 if (platformMimeHandler.Start () == MimeExtensionHandlerStatus.OK) {
112 platform = EPlatformHandler.GNOME;
113 } else {
114 MimeIconEngine.LargeIcons.Images.Clear ();
115 MimeIconEngine.SmallIcons.Images.Clear ();
116 platformMimeHandler = new PlatformDefaultHandler ();
117 platformMimeHandler.Start ();
119 } else {
120 SmallIcons.ImageSize = new Size (16, 16);
121 LargeIcons.ImageSize = new Size (48, 48);
123 platformMimeHandler = new PlatformDefaultHandler ();
124 platformMimeHandler.Start ();
128 public static int GetIconIndexForFile (string full_filename)
130 lock (lock_object) {
131 if (platform == EPlatformHandler.Default) {
132 return (int)MimeIconIndex ["unknown/unknown"];
135 string mime_type = Mime.GetMimeTypeForFile (full_filename);
137 object oindex = GetIconIndex (mime_type);
139 // not found, add it
140 if (oindex == null) {
141 int index = full_filename.IndexOf (':');
143 if (index > 1) {
144 oindex = MimeIconIndex ["unknown/unknown"];
146 } else {
147 oindex = platformMimeHandler.AddAndGetIconIndex (full_filename, mime_type);
149 // sanity check
150 if (oindex == null)
151 oindex = MimeIconIndex ["unknown/unknown"];
155 return (int)oindex;
159 public static int GetIconIndexForMimeType (string mime_type)
161 lock (lock_object) {
162 if (platform == EPlatformHandler.Default) {
163 if (mime_type == "inode/directory") {
164 return (int)MimeIconIndex ["inode/directory"];
165 } else {
166 return (int)MimeIconIndex ["unknown/unknown"];
170 object oindex = GetIconIndex (mime_type);
172 // not found, add it
173 if (oindex == null) {
174 oindex = platformMimeHandler.AddAndGetIconIndex (mime_type);
176 // sanity check
177 if (oindex == null)
178 oindex = MimeIconIndex ["unknown/unknown"];
181 return (int)oindex;
185 public static Image GetIconForMimeTypeAndSize (string mime_type, Size size)
187 lock (lock_object) {
188 object oindex = GetIconIndex (mime_type);
190 Bitmap bmp = new Bitmap (LargeIcons.Images [(int)oindex], size);
192 return bmp;
196 internal static void AddIconByImage (string mime_type, Image image)
198 int index = SmallIcons.Images.Add (image, Color.Transparent);
199 LargeIcons.Images.Add (image, Color.Transparent);
201 MimeIconIndex.Add (mime_type, index);
204 private static object GetIconIndex (string mime_type)
206 object oindex = null;
208 if (mime_type != null) {
209 // first check if mime_type is available in the mimetype/icon hashtable
210 oindex = MimeIconIndex [mime_type];
212 if (oindex == null) {
213 // it is not available, check if an alias exist for mime_type
214 string alias = Mime.GetMimeAlias (mime_type);
216 if (alias != null) {
217 string[] split = alias.Split (new char [] { ',' });
219 for (int i = 0; i < split.Length; i++) {
220 oindex = MimeIconIndex [split [i]];
222 if (oindex != null)
223 return oindex;
227 // if oindex is still null check if mime_type is a sub class of an other mime type
228 string sub_class = Mime.SubClasses [mime_type];
230 if (sub_class != null) {
231 oindex = MimeIconIndex [sub_class];
233 if (oindex != null)
234 return oindex;
237 // last check, see if we find an entry for the main mime type class
238 string mime_class_main = mime_type.Substring (0, mime_type.IndexOf ('/'));
239 return MimeIconIndex [mime_class_main];
243 return oindex;
247 internal abstract class PlatformMimeIconHandler
249 protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.OK;
251 public MimeExtensionHandlerStatus MimeExtensionHandlerStatus {
252 get {
253 return mimeExtensionHandlerStatus;
257 public abstract MimeExtensionHandlerStatus Start ();
259 public virtual object AddAndGetIconIndex (string filename, string mime_type)
261 return null;
264 public virtual object AddAndGetIconIndex (string mime_type)
266 return null;
270 internal class PlatformDefaultHandler : PlatformMimeIconHandler
272 public override MimeExtensionHandlerStatus Start ()
274 MimeIconEngine.AddIconByImage ("inode/directory", ResourceImageLoader.Get ("folder.png"));
275 MimeIconEngine.AddIconByImage ("unknown/unknown", ResourceImageLoader.Get ("text-x-generic.png"));
276 MimeIconEngine.AddIconByImage ("desktop/desktop", ResourceImageLoader.Get ("user-desktop.png"));
277 MimeIconEngine.AddIconByImage ("directory/home", ResourceImageLoader.Get ("user-home.png"));
279 MimeIconEngine.AddIconByImage ("network/network", ResourceImageLoader.Get ("folder-remote.png"));
280 MimeIconEngine.AddIconByImage ("recently/recently", ResourceImageLoader.Get ("document-open.png"));
281 MimeIconEngine.AddIconByImage ("workplace/workplace", ResourceImageLoader.Get ("computer.png"));
283 return MimeExtensionHandlerStatus.OK; // return always ok
287 internal class GnomeHandler : PlatformMimeIconHandler
289 public override MimeExtensionHandlerStatus Start ()
291 CreateUIIcons ();
293 return MimeExtensionHandlerStatus.OK;
296 private void CreateUIIcons ()
298 AddGnomeIcon ("unknown/unknown", "gnome-fs-regular");
299 AddGnomeIcon ("inode/directory", "gnome-fs-directory");
300 AddGnomeIcon ("directory/home", "gnome-fs-home");
301 AddGnomeIcon ("desktop/desktop", "gnome-fs-desktop");
302 AddGnomeIcon ("recently/recently", "gnome-fs-directory-accept");
303 AddGnomeIcon ("workplace/workplace", "gnome-fs-client");
305 AddGnomeIcon ("network/network", "gnome-fs-network");
306 AddGnomeIcon ("nfs/nfs", "gnome-fs-nfs");
307 AddGnomeIcon ("smb/smb", "gnome-fs-smb");
309 AddGnomeIcon ("harddisk/harddisk", "gnome-dev-harddisk");
310 AddGnomeIcon ("cdrom/cdrom", "gnome-dev-cdrom");
311 AddGnomeIcon ("removable/removable", "gnome-dev-removable");
314 private void AddGnomeIcon (string internal_mime_type, string name)
316 int index = -1;
318 if (MimeIconEngine.MimeIconIndex.ContainsKey (internal_mime_type)) {
319 return;
322 Image image = GnomeUtil.GetIcon (name, 48);
324 if (image == null) {
325 if (internal_mime_type == "unknown/unknown")
326 image = ResourceImageLoader.Get ("text-x-generic.png");
327 else
328 if (internal_mime_type == "inode/directory")
329 image = ResourceImageLoader.Get ("folder.png");
330 else
331 if (internal_mime_type == "directory/home")
332 image = ResourceImageLoader.Get ("user-home.png");
333 else
334 if (internal_mime_type == "desktop/desktop")
335 image = ResourceImageLoader.Get ("user-desktop.png");
336 else
337 if (internal_mime_type == "recently/recently")
338 image = ResourceImageLoader.Get ("document-open.png");
339 else
340 if (internal_mime_type == "workplace/workplace")
341 image = ResourceImageLoader.Get ("computer.png");
342 else
343 if (internal_mime_type == "network/network" || internal_mime_type == "nfs/nfs" || internal_mime_type == "smb/smb")
344 image = ResourceImageLoader.Get ("folder-remote.png");
345 else
346 if (internal_mime_type == "harddisk/harddisk" || internal_mime_type == "cdrom/cdrom" || internal_mime_type == "removable/removable")
347 image = ResourceImageLoader.Get ("text-x-generic.png");
350 index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
351 MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
353 MimeIconEngine.MimeIconIndex.Add (internal_mime_type, index);
356 public override object AddAndGetIconIndex (string filename, string mime_type)
358 int index = -1;
360 Image image = GnomeUtil.GetIcon (filename, mime_type, 48);
362 index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
363 MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
365 MimeIconEngine.MimeIconIndex.Add (mime_type, index);
367 return index;
370 public override object AddAndGetIconIndex (string mime_type)
372 int index = -1;
374 Image image = GnomeUtil.GetIcon (mime_type, 48);
376 index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
377 MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
379 MimeIconEngine.MimeIconIndex.Add (mime_type, index);
381 return index;
385 internal class GnomeUtil
387 const string libgdk = "libgdk-x11-2.0.so.0";
388 const string libgdk_pixbuf = "libgdk_pixbuf-2.0.so.0";
389 const string libgtk = "libgtk-x11-2.0.so.0";
390 const string libglib = "libglib-2.0.so.0";
391 const string libgobject = "libgobject-2.0.so.0";
392 const string libgnomeui = "libgnomeui-2.so.0";
393 const string librsvg = "librsvg-2.so.2";
395 [DllImport(librsvg)]
396 static extern IntPtr rsvg_pixbuf_from_file_at_size (string file_name, int width, int height, out IntPtr error);
398 [DllImport(libgdk_pixbuf)]
399 static extern bool gdk_pixbuf_save_to_buffer (IntPtr pixbuf, out IntPtr buffer, out UIntPtr buffer_size, string type, out IntPtr error, IntPtr option_dummy);
401 [DllImport(libglib)]
402 static extern void g_free (IntPtr mem);
404 [DllImport(libgdk)]
405 static extern bool gdk_init_check (IntPtr argc, IntPtr argv);
407 [DllImport(libgobject)]
408 static extern void g_object_unref (IntPtr nativeObject);
410 [DllImport(libgnomeui)]
411 static extern string gnome_icon_lookup (IntPtr icon_theme, IntPtr thumbnail_factory, string file_uri, string custom_icon, IntPtr file_info, string mime_type, GnomeIconLookupFlags flags, IntPtr result);
413 [DllImport(libgtk)]
414 static extern IntPtr gtk_icon_theme_get_default ();
416 [DllImport(libgtk)]
417 static extern IntPtr gtk_icon_theme_load_icon (IntPtr icon_theme, string icon_name, int size, GtkIconLookupFlags flags, out IntPtr error);
419 [DllImport(libgtk)]
420 static extern bool gtk_icon_theme_has_icon (IntPtr icon_theme, string icon_name);
422 enum GnomeIconLookupFlags
424 GNOME_ICON_LOOKUP_FLAGS_NONE = 0,
425 GNOME_ICON_LOOKUP_FLAGS_EMBEDDING_TEXT = 1<<0,
426 GNOME_ICON_LOOKUP_FLAGS_SHOW_SMALL_IMAGES_AS_THEMSELVES = 1<<1,
427 GNOME_ICON_LOOKUP_FLAGS_ALLOW_SVG_AS_THEMSELVES = 1<<2
430 enum GtkIconLookupFlags
432 GTK_ICON_LOOKUP_NO_SVG = 1 << 0,
433 GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1,
434 GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2
437 static bool inited = false;
439 static IntPtr default_icon_theme = IntPtr.Zero;
441 static void Init ()
443 gdk_init_check (IntPtr.Zero, IntPtr.Zero);
445 inited = true;
447 default_icon_theme = gtk_icon_theme_get_default ();
450 public static Image GetIcon (string file_name, string mime_type, int size)
452 if (!inited)
453 Init ();
455 Uri uri = new Uri (file_name);
457 string icon = gnome_icon_lookup (default_icon_theme, IntPtr.Zero, uri.AbsoluteUri,
458 null, IntPtr.Zero, mime_type,
459 GnomeIconLookupFlags.GNOME_ICON_LOOKUP_FLAGS_NONE, IntPtr.Zero);
461 IntPtr error = IntPtr.Zero;
462 IntPtr pixbuf = gtk_icon_theme_load_icon (default_icon_theme, icon, size,
463 GtkIconLookupFlags.GTK_ICON_LOOKUP_USE_BUILTIN, out error);
465 if (error != IntPtr.Zero)
466 return null;
468 return GdkPixbufToImage (pixbuf);
471 public static Image GetIcon (string icon, int size)
473 if (!inited)
474 Init ();
476 IntPtr error = IntPtr.Zero;
477 IntPtr pixbuf = gtk_icon_theme_load_icon (default_icon_theme, icon, size,
478 GtkIconLookupFlags.GTK_ICON_LOOKUP_USE_BUILTIN, out error);
480 if (error != IntPtr.Zero)
481 return null;
483 return GdkPixbufToImage (pixbuf);
486 public static Image GdkPixbufToImage (IntPtr pixbuf)
488 IntPtr error = IntPtr.Zero;
489 IntPtr buffer;
490 UIntPtr buffer_size_as_ptr;
491 string type = "png";
493 bool saved = gdk_pixbuf_save_to_buffer (pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
495 if (!saved)
496 return null;
498 int buffer_size = (int) (uint) buffer_size_as_ptr;
499 byte[] result = new byte [buffer_size];
500 Marshal.Copy (buffer, result, 0, (int) buffer_size);
501 g_free (buffer);
502 g_object_unref (pixbuf);
504 Image image = null;
505 using (MemoryStream s = new MemoryStream (result))
506 image = Image.FromStream (s);
508 return image;
511 public static Image GetSVGasImage (string filename, int width, int height)
513 if (!inited)
514 Init ();
516 if (!File.Exists (filename))
517 return null;
518 IntPtr error = IntPtr.Zero;
519 IntPtr pixbuf = rsvg_pixbuf_from_file_at_size (filename, width, height, out error);
521 if (error != IntPtr.Zero)
522 return null;
524 return GdkPixbufToImage (pixbuf);
527 public static bool HasImage (string name)
529 if (!inited)
530 Init ();
532 return gtk_icon_theme_has_icon (default_icon_theme, name);