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:
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
24 // Alexander Olk alex.olk@googlemail.com
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
33 using System
.Reflection
;
35 using System
.Collections
;
38 using System
.Runtime
.InteropServices
;
41 namespace System
.Windows
.Forms
43 internal enum MimeExtensionHandlerStatus
49 internal enum EPlatformHandler
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
)) {
63 Console
.WriteLine ("Failed to read {0}", name
);
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");
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
;
114 MimeIconEngine
.LargeIcons
.Images
.Clear ();
115 MimeIconEngine
.SmallIcons
.Images
.Clear ();
116 platformMimeHandler
= new PlatformDefaultHandler ();
117 platformMimeHandler
.Start ();
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
)
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
);
140 if (oindex
== null) {
141 int index
= full_filename
.IndexOf (':');
144 oindex
= MimeIconIndex
["unknown/unknown"];
147 oindex
= platformMimeHandler
.AddAndGetIconIndex (full_filename
, mime_type
);
151 oindex
= MimeIconIndex
["unknown/unknown"];
159 public static int GetIconIndexForMimeType (string mime_type
)
162 if (platform
== EPlatformHandler
.Default
) {
163 if (mime_type
== "inode/directory") {
164 return (int)MimeIconIndex
["inode/directory"];
166 return (int)MimeIconIndex
["unknown/unknown"];
170 object oindex
= GetIconIndex (mime_type
);
173 if (oindex
== null) {
174 oindex
= platformMimeHandler
.AddAndGetIconIndex (mime_type
);
178 oindex
= MimeIconIndex
["unknown/unknown"];
185 public static Image
GetIconForMimeTypeAndSize (string mime_type
, Size size
)
188 object oindex
= GetIconIndex (mime_type
);
190 Bitmap bmp
= new Bitmap (LargeIcons
.Images
[(int)oindex
], size
);
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
);
217 string[] split
= alias.Split (new char [] { ',' }
);
219 for (int i
= 0; i
< split
.Length
; i
++) {
220 oindex
= MimeIconIndex
[split
[i
]];
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
];
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
];
247 internal abstract class PlatformMimeIconHandler
249 protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus
= MimeExtensionHandlerStatus
.OK
;
251 public MimeExtensionHandlerStatus MimeExtensionHandlerStatus
{
253 return mimeExtensionHandlerStatus
;
257 public abstract MimeExtensionHandlerStatus
Start ();
259 public virtual object AddAndGetIconIndex (string filename
, string mime_type
)
264 public virtual object AddAndGetIconIndex (string mime_type
)
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 ()
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
)
318 if (MimeIconEngine
.MimeIconIndex
.ContainsKey (internal_mime_type
)) {
322 Image image
= GnomeUtil
.GetIcon (name
, 48);
325 if (internal_mime_type
== "unknown/unknown")
326 image
= ResourceImageLoader
.Get ("text-x-generic.png");
328 if (internal_mime_type
== "inode/directory")
329 image
= ResourceImageLoader
.Get ("folder.png");
331 if (internal_mime_type
== "directory/home")
332 image
= ResourceImageLoader
.Get ("user-home.png");
334 if (internal_mime_type
== "desktop/desktop")
335 image
= ResourceImageLoader
.Get ("user-desktop.png");
337 if (internal_mime_type
== "recently/recently")
338 image
= ResourceImageLoader
.Get ("document-open.png");
340 if (internal_mime_type
== "workplace/workplace")
341 image
= ResourceImageLoader
.Get ("computer.png");
343 if (internal_mime_type
== "network/network" || internal_mime_type
== "nfs/nfs" || internal_mime_type
== "smb/smb")
344 image
= ResourceImageLoader
.Get ("folder-remote.png");
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
)
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
);
370 public override object AddAndGetIconIndex (string mime_type
)
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
);
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";
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
);
402 static extern void g_free (IntPtr mem
);
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
);
414 static extern IntPtr
gtk_icon_theme_get_default ();
417 static extern IntPtr
gtk_icon_theme_load_icon (IntPtr icon_theme
, string icon_name
, int size
, GtkIconLookupFlags flags
, out IntPtr error
);
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
;
443 gdk_init_check (IntPtr
.Zero
, IntPtr
.Zero
);
447 default_icon_theme
= gtk_icon_theme_get_default ();
450 public static Image
GetIcon (string file_name
, string mime_type
, int size
)
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
)
468 return GdkPixbufToImage (pixbuf
);
471 public static Image
GetIcon (string icon
, int size
)
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
)
483 return GdkPixbufToImage (pixbuf
);
486 public static Image
GdkPixbufToImage (IntPtr pixbuf
)
488 IntPtr error
= IntPtr
.Zero
;
490 UIntPtr buffer_size_as_ptr
;
493 bool saved
= gdk_pixbuf_save_to_buffer (pixbuf
, out buffer
, out buffer_size_as_ptr
, type
, out error
, IntPtr
.Zero
);
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
);
502 g_object_unref (pixbuf
);
505 using (MemoryStream s
= new MemoryStream (result
))
506 image
= Image
.FromStream (s
);
511 public static Image
GetSVGasImage (string filename
, int width
, int height
)
516 if (!File
.Exists (filename
))
518 IntPtr error
= IntPtr
.Zero
;
519 IntPtr pixbuf
= rsvg_pixbuf_from_file_at_size (filename
, width
, height
, out error
);
521 if (error
!= IntPtr
.Zero
)
524 return GdkPixbufToImage (pixbuf
);
527 public static bool HasImage (string name
)
532 return gtk_icon_theme_has_icon (default_icon_theme
, name
);