22
using System.Reflection;
22
23
using System.Collections.Generic;
23
using System.Reflection;
31
30
public static class IconProvider
34
32
public static readonly Pixbuf UnknownPixbuf;
35
public const int DefaultIconSize = 80;
33
const int DefaultIconSize = 80;
37
// Cache of loaded icons: key is "iconname_size".
38
static Dictionary<string, Pixbuf> pixbufCache;
40
static IconTheme [] themes;
42
36
static IconProvider ()
44
pixbufCache = new Dictionary<string, Pixbuf> ();
46
38
UnknownPixbuf = new Pixbuf (Colorspace.Rgb, true, 8, 1, 1);
47
39
UnknownPixbuf.Fill (0x00000000);
49
themes = new IconTheme [2];
50
themes [0] = IconTheme.Default;
52
IconTheme.Default.Changed += OnDefaultIconThemeChanged;
42
static bool IconIsEmbeddedResource (string name)
44
return name.IndexOf ("@") > 0;
47
static bool IconIsFile (string name)
49
return name.StartsWith ("/") ||
50
name.StartsWith ("~/") ||
51
name.StartsWith ("file://",
52
StringComparison.OrdinalIgnoreCase);
55
static Pixbuf IconFromEmbeddedResource (string name, int size)
58
string resource, assemblyName;
60
resource = name.Substring (0, name.IndexOf ("@"));
61
assemblyName = name.Substring (resource.Length + 1);
63
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies ()) {
64
if (asm.FullName != assemblyName) continue;
65
pixbuf = new Pixbuf (asm, resource, size, size);
68
} catch (Exception e) {
69
Console.Error.WriteLine ("Failed to load icon resource {0} " +
70
"from assembly {1}: {2}", resource, assemblyName, e.Message);
76
static Pixbuf IconFromFile (string name, int size)
80
name = name.Replace ("~", Paths.UserHome);
82
pixbuf = new Pixbuf (name, size, size);
89
static Pixbuf IconFromTheme (string name, int size, IconTheme theme)
94
// We may have to remove the extension.
95
if (name.Contains (".")) {
96
name_noext = name.Remove (name.LastIndexOf ("."));
101
if (theme.HasIcon (name)) {
102
pixbuf = theme.LoadIcon (name, size, 0);
103
} else if (theme.HasIcon (name_noext)) {
104
pixbuf = theme.LoadIcon (name_noext, size, 0);
105
} else if (name == "gnome-mime-text-plain" &&
106
theme.HasIcon ("gnome-mime-text")) {
107
pixbuf = theme.LoadIcon ("gnome-mime-text", size, 0);
117
static Pixbuf GenericFileIcon (int size)
119
Pixbuf pixbuf = null;
120
if (IconTheme.Default.HasIcon ("gtk-file")) {
122
pixbuf = IconTheme.Default.LoadIcon ("gtk-file", size, 0);
130
static Pixbuf UnknownIcon (int size)
132
Pixbuf pixbuf = null;
134
if (IconTheme.Default.HasIcon ("emblem-noread")) {
136
pixbuf = IconTheme.Default.LoadIcon ("emblem-noread", size, 0);
55
144
public static Pixbuf PixbufFromIconName (string name, int size)
58
string name_noext, iconKey, resourceName, resourceNamespace;
61
if (string.IsNullOrEmpty (name)) return null;
63
// Is the icon name in cache?
64
iconKey = string.Format ("{0}_{1}", name, size);
65
if (pixbufCache.TryGetValue (iconKey, out pixbuf)) {
69
// TODO: Use a GNOME ThumbnailFactory
71
// The icon can be loaded from a loaded assembly if the icon has
72
// the format: "resource@assemblyname".
74
if (name.IndexOf ("@") > 0) {
75
resourceName = name.Substring (0, name.IndexOf ("@"));
76
resourceNamespace = name.Substring (resourceName.Length +1);
78
// loop though all loaded assemblies in the AppDomain
79
foreach (Assembly asmb in AppDomain.CurrentDomain.GetAssemblies ()) {
80
if (new AssemblyName (asmb.FullName).Name.Equals (resourceNamespace)) {
82
pixbuf = new Pixbuf (asmb, resourceName, size, size);
85
// TODO: Should we log this error?
91
if (name.StartsWith ("/") ||
92
name.StartsWith ("~/") ||
93
name.StartsWith ("file://", StringComparison.OrdinalIgnoreCase)) {
95
pixbuf = new Pixbuf (name, size, size);
97
// Could not load from file.
101
if (name.Contains (".")) {
102
name_noext = name.Remove (name.LastIndexOf ("."));
108
theme = IconTheme.Default;
110
if (theme.HasIcon (name)) {
111
pixbuf = theme.LoadIcon (name, size, 0);
113
else if (theme.HasIcon (name_noext)) {
114
pixbuf = theme.LoadIcon (name_noext, size, 0);
116
else if (name == "gnome-mime-text-plain" &&
117
theme.HasIcon ("gnome-mime-text")) {
118
pixbuf = theme.LoadIcon ("gnome-mime-text", size, 0);
125
// Try Tango theme if no icon was found.
126
// This code duplication (loop unrolling) was necessary
127
// becuase something funny was happening with the icon loading
128
// when using themes stored in an array.
129
if (pixbuf == null) {
130
theme = new IconTheme ();
131
theme.CustomTheme = "Tango";
133
if (theme.HasIcon (name)) {
134
pixbuf = theme.LoadIcon (name, size, 0);
136
else if (theme.HasIcon (name_noext)) {
137
pixbuf = theme.LoadIcon (name_noext, size, 0);
139
else if (name == "gnome-mime-text-plain" &&
140
theme.HasIcon ("gnome-mime-text")) {
141
pixbuf = theme.LoadIcon ("gnome-mime-text", size, 0);
149
theme = IconTheme.Default;
150
if (pixbuf == null && name.StartsWith ("gnome-mime") &&
151
themes [0].HasIcon ("gtk-file")) {
153
pixbuf = themes [0].LoadIcon ("gtk-file", size, 0);
158
if (pixbuf == null && themes [0].HasIcon ("emblem-noread")) {
160
pixbuf = themes [0].LoadIcon ("emblem-noread", size, 0);
167
if (pixbuf == null) {
149
throw new ArgumentNullException ("name");
152
// The icon can be loaded from a loaded assembly if the icon has
153
// the format: "resource@assemblyname".
154
if (IconIsEmbeddedResource (name)) {
155
pixbuf = IconFromEmbeddedResource (name, size);
158
if (IconIsFile (name)) {
159
pixbuf = IconFromFile (name, size);
162
// Try to load icon from defaul theme.
163
pixbuf = IconFromTheme (name, size, IconTheme.Default);
165
// Try to load a generic file icon.
166
if (pixbuf == null && name.StartsWith ("gnome-mime"))
167
pixbuf = GenericFileIcon (size);
170
// Try to load a pretty "no icon found" icon.
172
pixbuf = UnknownIcon (size);
173
// If all else fails, use the UnknownPixbuf.
168
175
pixbuf = UnknownPixbuf;
170
// Cache icon pixbuf.
171
if (pixbuf != null && pixbuf != UnknownPixbuf) {
172
pixbufCache [iconKey] = pixbuf;
178
static void OnDefaultIconThemeChanged (object sender, EventArgs args)
180
pixbufCache.Clear ();