a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
557 lines
16 KiB
C#
557 lines
16 KiB
C#
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
// Copyright (c) 2006 Alexander Olk
|
|
//
|
|
// Authors:
|
|
//
|
|
// Alexander Olk alex.olk@googlemail.com
|
|
//
|
|
|
|
// use
|
|
// public static int GetIconIndexForFile( string full_filename )
|
|
// public static int GetIconIndexForMimeType( string mime_type )
|
|
// to get the image index in MimeIconEngine.SmallIcons and MimeIconEngine.LargeIcons
|
|
|
|
using System;
|
|
using System.Reflection;
|
|
using System.Drawing;
|
|
using System.Collections;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Runtime.InteropServices;
|
|
using System.Xml;
|
|
|
|
namespace System.Windows.Forms
|
|
{
|
|
internal enum MimeExtensionHandlerStatus
|
|
{
|
|
OK,
|
|
ERROR
|
|
}
|
|
|
|
internal enum EPlatformHandler
|
|
{
|
|
Default,
|
|
GNOME
|
|
}
|
|
|
|
internal class ResourceImageLoader
|
|
{
|
|
static Assembly assembly = typeof (ResourceImageLoader).Assembly;
|
|
|
|
static internal Bitmap Get (string name)
|
|
{
|
|
Stream stream = assembly.GetManifestResourceStream (name);
|
|
|
|
if (stream == null) {
|
|
Console.WriteLine ("Failed to read {0}", name);
|
|
return null;
|
|
}
|
|
|
|
return new Bitmap (stream);
|
|
}
|
|
|
|
static internal Icon GetIcon (string name)
|
|
{
|
|
Stream stream = assembly.GetManifestResourceStream (name);
|
|
|
|
if (stream == null) {
|
|
Console.WriteLine ("Failed to read {0}", name);
|
|
return null;
|
|
}
|
|
|
|
return new Icon (stream);
|
|
}
|
|
}
|
|
|
|
internal class MimeIconEngine
|
|
{
|
|
public static ImageList SmallIcons = new ImageList();
|
|
public static ImageList LargeIcons = new ImageList();
|
|
|
|
private static EPlatformHandler platform = EPlatformHandler.Default;
|
|
|
|
internal static Hashtable MimeIconIndex = new Hashtable ();
|
|
|
|
private static PlatformMimeIconHandler platformMimeHandler = null;
|
|
|
|
private static object lock_object = new Object();
|
|
|
|
static MimeIconEngine ()
|
|
{
|
|
SmallIcons.ColorDepth = ColorDepth.Depth32Bit;
|
|
SmallIcons.TransparentColor = Color.Transparent;
|
|
LargeIcons.ColorDepth = ColorDepth.Depth32Bit;
|
|
LargeIcons.TransparentColor = Color.Transparent;
|
|
|
|
string session = Environment.GetEnvironmentVariable ("DESKTOP_SESSION");
|
|
|
|
if (session != null) {
|
|
session = session.ToUpper ();
|
|
|
|
if (session == "DEFAULT") {
|
|
string helper = Environment.GetEnvironmentVariable ("GNOME_DESKTOP_SESSION_ID");
|
|
|
|
if (helper != null)
|
|
session = "GNOME";
|
|
}
|
|
} else
|
|
session = String.Empty;
|
|
|
|
if (Mime.MimeAvailable && session == "GNOME") {
|
|
SmallIcons.ImageSize = new Size (24, 24);
|
|
LargeIcons.ImageSize = new Size (48, 48);
|
|
|
|
platformMimeHandler = new GnomeHandler ();
|
|
if (platformMimeHandler.Start () == MimeExtensionHandlerStatus.OK) {
|
|
platform = EPlatformHandler.GNOME;
|
|
} else {
|
|
MimeIconEngine.LargeIcons.Images.Clear ();
|
|
MimeIconEngine.SmallIcons.Images.Clear ();
|
|
platformMimeHandler = new PlatformDefaultHandler ();
|
|
platformMimeHandler.Start ();
|
|
}
|
|
} else {
|
|
SmallIcons.ImageSize = new Size (16, 16);
|
|
LargeIcons.ImageSize = new Size (48, 48);
|
|
|
|
platformMimeHandler = new PlatformDefaultHandler ();
|
|
platformMimeHandler.Start ();
|
|
}
|
|
}
|
|
|
|
public static int GetIconIndexForFile (string full_filename)
|
|
{
|
|
lock (lock_object) {
|
|
if (platform == EPlatformHandler.Default) {
|
|
return (int)MimeIconIndex ["unknown/unknown"];
|
|
}
|
|
|
|
string mime_type = Mime.GetMimeTypeForFile (full_filename);
|
|
|
|
object oindex = GetIconIndex (mime_type);
|
|
|
|
// not found, add it
|
|
if (oindex == null) {
|
|
int index = full_filename.IndexOf (':');
|
|
|
|
if (index > 1) {
|
|
oindex = MimeIconIndex ["unknown/unknown"];
|
|
|
|
} else {
|
|
oindex = platformMimeHandler.AddAndGetIconIndex (full_filename, mime_type);
|
|
|
|
// sanity check
|
|
if (oindex == null)
|
|
oindex = MimeIconIndex ["unknown/unknown"];
|
|
}
|
|
}
|
|
|
|
return (int)oindex;
|
|
}
|
|
}
|
|
|
|
public static int GetIconIndexForMimeType (string mime_type)
|
|
{
|
|
lock (lock_object) {
|
|
if (platform == EPlatformHandler.Default) {
|
|
if (mime_type == "inode/directory") {
|
|
return (int)MimeIconIndex ["inode/directory"];
|
|
} else {
|
|
return (int)MimeIconIndex ["unknown/unknown"];
|
|
}
|
|
}
|
|
|
|
object oindex = GetIconIndex (mime_type);
|
|
|
|
// not found, add it
|
|
if (oindex == null) {
|
|
oindex = platformMimeHandler.AddAndGetIconIndex (mime_type);
|
|
|
|
// sanity check
|
|
if (oindex == null)
|
|
oindex = MimeIconIndex ["unknown/unknown"];
|
|
}
|
|
|
|
return (int)oindex;
|
|
}
|
|
}
|
|
|
|
public static Image GetIconForMimeTypeAndSize (string mime_type, Size size)
|
|
{
|
|
lock (lock_object) {
|
|
object oindex = GetIconIndex (mime_type);
|
|
|
|
Bitmap bmp = new Bitmap (LargeIcons.Images [(int)oindex], size);
|
|
|
|
return bmp;
|
|
}
|
|
}
|
|
|
|
internal static void AddIconByImage (string mime_type, Image image)
|
|
{
|
|
int index = SmallIcons.Images.Add (image, Color.Transparent);
|
|
LargeIcons.Images.Add (image, Color.Transparent);
|
|
|
|
MimeIconIndex.Add (mime_type, index);
|
|
}
|
|
|
|
private static object GetIconIndex (string mime_type)
|
|
{
|
|
object oindex = null;
|
|
|
|
if (mime_type != null) {
|
|
// first check if mime_type is available in the mimetype/icon hashtable
|
|
oindex = MimeIconIndex [mime_type];
|
|
|
|
if (oindex == null) {
|
|
// it is not available, check if an alias exist for mime_type
|
|
string alias = Mime.GetMimeAlias (mime_type);
|
|
|
|
if (alias != null) {
|
|
string[] split = alias.Split (new char [] { ',' });
|
|
|
|
for (int i = 0; i < split.Length; i++) {
|
|
oindex = MimeIconIndex [split [i]];
|
|
|
|
if (oindex != null)
|
|
return oindex;
|
|
}
|
|
}
|
|
|
|
// if oindex is still null check if mime_type is a sub class of an other mime type
|
|
string sub_class = Mime.SubClasses [mime_type];
|
|
|
|
if (sub_class != null) {
|
|
oindex = MimeIconIndex [sub_class];
|
|
|
|
if (oindex != null)
|
|
return oindex;
|
|
}
|
|
|
|
// last check, see if we find an entry for the main mime type class
|
|
string mime_class_main = mime_type.Substring (0, mime_type.IndexOf ('/'));
|
|
return MimeIconIndex [mime_class_main];
|
|
}
|
|
}
|
|
|
|
return oindex;
|
|
}
|
|
}
|
|
|
|
internal abstract class PlatformMimeIconHandler
|
|
{
|
|
protected MimeExtensionHandlerStatus mimeExtensionHandlerStatus = MimeExtensionHandlerStatus.OK;
|
|
|
|
public MimeExtensionHandlerStatus MimeExtensionHandlerStatus {
|
|
get {
|
|
return mimeExtensionHandlerStatus;
|
|
}
|
|
}
|
|
|
|
public abstract MimeExtensionHandlerStatus Start ();
|
|
|
|
public virtual object AddAndGetIconIndex (string filename, string mime_type)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public virtual object AddAndGetIconIndex (string mime_type)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
internal class PlatformDefaultHandler : PlatformMimeIconHandler
|
|
{
|
|
public override MimeExtensionHandlerStatus Start ()
|
|
{
|
|
MimeIconEngine.AddIconByImage ("inode/directory", ResourceImageLoader.Get ("folder.png"));
|
|
MimeIconEngine.AddIconByImage ("unknown/unknown", ResourceImageLoader.Get ("text-x-generic.png"));
|
|
MimeIconEngine.AddIconByImage ("desktop/desktop", ResourceImageLoader.Get ("user-desktop.png"));
|
|
MimeIconEngine.AddIconByImage ("directory/home", ResourceImageLoader.Get ("user-home.png"));
|
|
|
|
MimeIconEngine.AddIconByImage ("network/network", ResourceImageLoader.Get ("folder-remote.png"));
|
|
MimeIconEngine.AddIconByImage ("recently/recently", ResourceImageLoader.Get ("document-open.png"));
|
|
MimeIconEngine.AddIconByImage ("workplace/workplace", ResourceImageLoader.Get ("computer.png"));
|
|
|
|
return MimeExtensionHandlerStatus.OK; // return always ok
|
|
}
|
|
}
|
|
|
|
internal class GnomeHandler : PlatformMimeIconHandler
|
|
{
|
|
public override MimeExtensionHandlerStatus Start ()
|
|
{
|
|
CreateUIIcons ();
|
|
|
|
return MimeExtensionHandlerStatus.OK;
|
|
}
|
|
|
|
private void CreateUIIcons ()
|
|
{
|
|
AddGnomeIcon ("unknown/unknown", "gnome-fs-regular");
|
|
AddGnomeIcon ("inode/directory", "gnome-fs-directory");
|
|
AddGnomeIcon ("directory/home", "gnome-fs-home");
|
|
AddGnomeIcon ("desktop/desktop", "gnome-fs-desktop");
|
|
AddGnomeIcon ("recently/recently", "gnome-fs-directory-accept");
|
|
AddGnomeIcon ("workplace/workplace", "gnome-fs-client");
|
|
|
|
AddGnomeIcon ("network/network", "gnome-fs-network");
|
|
AddGnomeIcon ("nfs/nfs", "gnome-fs-nfs");
|
|
AddGnomeIcon ("smb/smb", "gnome-fs-smb");
|
|
|
|
AddGnomeIcon ("harddisk/harddisk", "gnome-dev-harddisk");
|
|
AddGnomeIcon ("cdrom/cdrom", "gnome-dev-cdrom");
|
|
AddGnomeIcon ("removable/removable", "gnome-dev-removable");
|
|
}
|
|
|
|
private void AddGnomeIcon (string internal_mime_type, string name)
|
|
{
|
|
int index = -1;
|
|
|
|
if (MimeIconEngine.MimeIconIndex.ContainsKey (internal_mime_type)) {
|
|
return;
|
|
}
|
|
|
|
Image image = GnomeUtil.GetIcon (name, 48);
|
|
|
|
if (image == null) {
|
|
if (internal_mime_type == "unknown/unknown")
|
|
image = ResourceImageLoader.Get ("text-x-generic.png");
|
|
else
|
|
if (internal_mime_type == "inode/directory")
|
|
image = ResourceImageLoader.Get ("folder.png");
|
|
else
|
|
if (internal_mime_type == "directory/home")
|
|
image = ResourceImageLoader.Get ("user-home.png");
|
|
else
|
|
if (internal_mime_type == "desktop/desktop")
|
|
image = ResourceImageLoader.Get ("user-desktop.png");
|
|
else
|
|
if (internal_mime_type == "recently/recently")
|
|
image = ResourceImageLoader.Get ("document-open.png");
|
|
else
|
|
if (internal_mime_type == "workplace/workplace")
|
|
image = ResourceImageLoader.Get ("computer.png");
|
|
else
|
|
if (internal_mime_type == "network/network" || internal_mime_type == "nfs/nfs" || internal_mime_type == "smb/smb")
|
|
image = ResourceImageLoader.Get ("folder-remote.png");
|
|
else
|
|
if (internal_mime_type == "harddisk/harddisk" || internal_mime_type == "cdrom/cdrom" || internal_mime_type == "removable/removable")
|
|
image = ResourceImageLoader.Get ("text-x-generic.png");
|
|
}
|
|
|
|
if (image != null) {
|
|
index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.MimeIconIndex.Add (internal_mime_type, index);
|
|
}
|
|
}
|
|
|
|
public override object AddAndGetIconIndex (string filename, string mime_type)
|
|
{
|
|
int index = -1;
|
|
|
|
Image image = GnomeUtil.GetIcon (filename, mime_type, 48);
|
|
if (image != null) {
|
|
index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.MimeIconIndex.Add (mime_type, index);
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
public override object AddAndGetIconIndex (string mime_type)
|
|
{
|
|
int index = -1;
|
|
|
|
Image image = GnomeUtil.GetIcon (mime_type, 48);
|
|
if (image != null) {
|
|
index = MimeIconEngine.SmallIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.LargeIcons.Images.Add (image, Color.Transparent);
|
|
MimeIconEngine.MimeIconIndex.Add (mime_type, index);
|
|
}
|
|
|
|
return index;
|
|
}
|
|
}
|
|
|
|
internal class GnomeUtil
|
|
{
|
|
const string libgdk = "libgdk-x11-2.0.so.0";
|
|
const string libgdk_pixbuf = "libgdk_pixbuf-2.0.so.0";
|
|
const string libgtk = "libgtk-x11-2.0.so.0";
|
|
const string libglib = "libglib-2.0.so.0";
|
|
const string libgobject = "libgobject-2.0.so.0";
|
|
const string libgnomeui = "libgnomeui-2.so.0";
|
|
const string librsvg = "librsvg-2.so.2";
|
|
|
|
[DllImport(librsvg)]
|
|
static extern IntPtr rsvg_pixbuf_from_file_at_size (string file_name, int width, int height, out IntPtr error);
|
|
|
|
[DllImport(libgdk_pixbuf)]
|
|
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);
|
|
|
|
[DllImport(libglib)]
|
|
static extern void g_free (IntPtr mem);
|
|
|
|
[DllImport(libgdk)]
|
|
static extern bool gdk_init_check (IntPtr argc, IntPtr argv);
|
|
|
|
[DllImport(libgobject)]
|
|
static extern void g_object_unref (IntPtr nativeObject);
|
|
|
|
[DllImport(libgnomeui)]
|
|
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);
|
|
|
|
[DllImport(libgtk)]
|
|
static extern IntPtr gtk_icon_theme_get_default ();
|
|
|
|
[DllImport(libgtk)]
|
|
static extern IntPtr gtk_icon_theme_load_icon (IntPtr icon_theme, string icon_name, int size, GtkIconLookupFlags flags, out IntPtr error);
|
|
|
|
[DllImport(libgtk)]
|
|
static extern bool gtk_icon_theme_has_icon (IntPtr icon_theme, string icon_name);
|
|
|
|
enum GnomeIconLookupFlags
|
|
{
|
|
GNOME_ICON_LOOKUP_FLAGS_NONE = 0,
|
|
GNOME_ICON_LOOKUP_FLAGS_EMBEDDING_TEXT = 1<<0,
|
|
GNOME_ICON_LOOKUP_FLAGS_SHOW_SMALL_IMAGES_AS_THEMSELVES = 1<<1,
|
|
GNOME_ICON_LOOKUP_FLAGS_ALLOW_SVG_AS_THEMSELVES = 1<<2
|
|
};
|
|
|
|
enum GtkIconLookupFlags
|
|
{
|
|
GTK_ICON_LOOKUP_NO_SVG = 1 << 0,
|
|
GTK_ICON_LOOKUP_FORCE_SVG = 1 << 1,
|
|
GTK_ICON_LOOKUP_USE_BUILTIN = 1 << 2
|
|
};
|
|
|
|
static bool inited = false;
|
|
|
|
static IntPtr default_icon_theme = IntPtr.Zero;
|
|
|
|
static void Init ()
|
|
{
|
|
gdk_init_check (IntPtr.Zero, IntPtr.Zero);
|
|
|
|
inited = true;
|
|
|
|
default_icon_theme = gtk_icon_theme_get_default ();
|
|
}
|
|
|
|
public static Image GetIcon (string file_name, string mime_type, int size)
|
|
{
|
|
if (!inited)
|
|
Init ();
|
|
|
|
Uri uri = new Uri (file_name);
|
|
|
|
string icon;
|
|
|
|
try {
|
|
icon = gnome_icon_lookup (default_icon_theme, IntPtr.Zero, uri.AbsoluteUri,
|
|
null, IntPtr.Zero, mime_type,
|
|
GnomeIconLookupFlags.GNOME_ICON_LOOKUP_FLAGS_NONE, IntPtr.Zero);
|
|
} catch {
|
|
// If libgnomeui is not installed, in preparation for Gnome 3
|
|
return null;
|
|
}
|
|
|
|
IntPtr error = IntPtr.Zero;
|
|
IntPtr pixbuf = gtk_icon_theme_load_icon (default_icon_theme, icon, size,
|
|
GtkIconLookupFlags.GTK_ICON_LOOKUP_USE_BUILTIN, out error);
|
|
|
|
if (error != IntPtr.Zero)
|
|
return null;
|
|
|
|
return GdkPixbufToImage (pixbuf);
|
|
}
|
|
|
|
public static Image GetIcon (string icon, int size)
|
|
{
|
|
if (!inited)
|
|
Init ();
|
|
|
|
IntPtr error = IntPtr.Zero;
|
|
IntPtr pixbuf = gtk_icon_theme_load_icon (default_icon_theme, icon, size,
|
|
GtkIconLookupFlags.GTK_ICON_LOOKUP_USE_BUILTIN, out error);
|
|
|
|
if (error != IntPtr.Zero)
|
|
return null;
|
|
|
|
return GdkPixbufToImage (pixbuf);
|
|
}
|
|
|
|
public static Image GdkPixbufToImage (IntPtr pixbuf)
|
|
{
|
|
IntPtr error = IntPtr.Zero;
|
|
IntPtr buffer;
|
|
UIntPtr buffer_size_as_ptr;
|
|
string type = "png";
|
|
|
|
bool saved = gdk_pixbuf_save_to_buffer (pixbuf, out buffer, out buffer_size_as_ptr, type, out error, IntPtr.Zero);
|
|
|
|
if (!saved)
|
|
return null;
|
|
|
|
int buffer_size = (int) (uint) buffer_size_as_ptr;
|
|
byte[] result = new byte [buffer_size];
|
|
Marshal.Copy (buffer, result, 0, (int) buffer_size);
|
|
g_free (buffer);
|
|
g_object_unref (pixbuf);
|
|
|
|
Image image = null;
|
|
MemoryStream s = new MemoryStream (result);
|
|
image = Image.FromStream (s);
|
|
|
|
return image;
|
|
}
|
|
|
|
public static Image GetSVGasImage (string filename, int width, int height)
|
|
{
|
|
if (!inited)
|
|
Init ();
|
|
|
|
if (!File.Exists (filename))
|
|
return null;
|
|
IntPtr error = IntPtr.Zero;
|
|
IntPtr pixbuf = rsvg_pixbuf_from_file_at_size (filename, width, height, out error);
|
|
|
|
if (error != IntPtr.Zero)
|
|
return null;
|
|
|
|
return GdkPixbufToImage (pixbuf);
|
|
}
|
|
|
|
public static bool HasImage (string name)
|
|
{
|
|
if (!inited)
|
|
Init ();
|
|
|
|
return gtk_icon_theme_has_icon (default_icon_theme, name);
|
|
}
|
|
}
|
|
}
|
|
|