~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to src/core/MonoDevelop.Ide/MonoDevelop.Ide/ImageService.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
using MonoDevelop.Core;
34
34
using MonoDevelop.Components;
35
35
using System.Text;
 
36
using System.Linq;
 
37
using MonoDevelop.Ide.Gui.Components;
36
38
 
37
39
namespace MonoDevelop.Ide
38
40
{
39
41
        public static class ImageService
40
42
        {
41
43
                static Gtk.IconFactory iconFactory = new Gtk.IconFactory ();
 
44
 
 
45
                // Mapping of icon spec to stock icon id.
42
46
                static List<Dictionary<string, string>> addinIcons = new List<Dictionary<string, string>> ();
 
47
 
 
48
                // Mapping of icon spec to stock icon id, but used only when the icon is not bound to a specific add-in
 
49
                static Dictionary<string, string> iconSpecToStockId = new Dictionary<string, string> ();
 
50
 
 
51
                // Map of all animations
 
52
                static Dictionary<string, AnimatedIcon> animationFactory = new Dictionary<string, AnimatedIcon> ();
 
53
 
43
54
                static List<RuntimeAddin> addins = new List<RuntimeAddin> ();
44
55
                static Dictionary<string, string> composedIcons = new Dictionary<string, string> ();
45
56
                static Dictionary<Gdk.Pixbuf, string> namedIcons = new Dictionary<Gdk.Pixbuf, string> ();
 
57
 
 
58
                // Dictionary of extension nodes by stock icon id. It holds nodes that have not yet been loaded
46
59
                static Dictionary<string, List<StockIconCodon>> iconStock = new Dictionary<string, List<StockIconCodon>> ();
47
60
                
48
61
                static Gtk.Requisition[] iconSizes = new Gtk.Requisition[7];
78
91
                {
79
92
                        try {
80
93
                                Gdk.Pixbuf pixbuf = null;
 
94
                                AnimatedIcon animatedIcon = null;
 
95
 
81
96
                                if (!string.IsNullOrEmpty (iconCodon.Resource) || !string.IsNullOrEmpty (iconCodon.File)) {
82
97
                                        // using the stream directly produces a gdk warning.
83
98
                                        byte[] buffer;
97
112
                                        }
98
113
                                        pixbuf = new Gdk.Pixbuf (buffer);
99
114
                                } else if (!string.IsNullOrEmpty (iconCodon.IconId)) {
100
 
                                        pixbuf = GetPixbuf (InternalGetStockId (iconCodon.Addin, iconCodon.IconId, iconCodon.IconSize), iconCodon.IconSize);
 
115
                                        var id = GetStockIdForImageSpec (iconCodon.Addin, iconCodon.IconId, iconCodon.IconSize);
 
116
                                        pixbuf = GetPixbuf (id, iconCodon.IconSize);
 
117
                                        // This may be an animation, get it
 
118
                                        animationFactory.TryGetValue (id, out animatedIcon);
 
119
                                } else if (!string.IsNullOrEmpty (iconCodon.Animation)) {
 
120
                                        string id = GetStockIdForImageSpec (iconCodon.Addin, "animation:" + iconCodon.Animation, iconCodon.IconSize);
 
121
                                        pixbuf = GetPixbuf (id, iconCodon.IconSize);
 
122
                                        // This *should* be an animation
 
123
                                        animationFactory.TryGetValue (id, out animatedIcon);
101
124
                                }
102
 
                                if (pixbuf != null) {
103
 
                                        Gtk.IconSize size = forceWildcard? Gtk.IconSize.Invalid : iconCodon.IconSize;
 
125
 
 
126
                                Gtk.IconSize size = forceWildcard? Gtk.IconSize.Invalid : iconCodon.IconSize;
 
127
                                if (pixbuf != null)
104
128
                                        AddToIconFactory (iconCodon.StockId, pixbuf, size);
105
 
                                }
 
129
                                if (animatedIcon != null)
 
130
                                        AddToAnimatedIconFactory (iconCodon.StockId, animatedIcon);
106
131
                        } catch (Exception ex) {
107
132
                                LoggingService.LogError (string.Format ("Error loading icon '{0}'", iconCodon.StockId), ex);
108
133
                        }
138
163
                        return copy;
139
164
                }
140
165
                
 
166
                public static Gdk.Pixbuf MakeInverted (Gdk.Pixbuf icon)
 
167
                {
 
168
                        if (icon.BitsPerSample != 8)
 
169
                                throw new NotSupportedException ();
 
170
                        Gdk.Pixbuf copy = icon.Copy ();
 
171
                        unsafe {
 
172
                                byte* pix = (byte*)copy.Pixels;
 
173
                                bool hasAlpha = copy.HasAlpha;
 
174
                                for (int y = 0; y < copy.Height; y++) {
 
175
                                        var start = pix;
 
176
                                        for (int x = 0; x < copy.Width; x++) {
 
177
                                                pix [0] = (byte)~pix [0];
 
178
                                                pix [1] = (byte)~pix [1];
 
179
                                                pix [2] = (byte)~pix [2];
 
180
                                                pix += hasAlpha ? 4 : 3;
 
181
                                        }
 
182
                                        pix = start + copy.Rowstride;
 
183
                                }
 
184
                        }
 
185
                        return copy;
 
186
                }
 
187
                
141
188
                public static Gdk.Pixbuf GetPixbuf (string name)
142
189
                {
143
190
                        return GetPixbuf (name, Gtk.IconSize.Button);
154
201
                                LoggingService.LogWarning ("Empty icon requested. Stack Trace: " + Environment.NewLine + Environment.StackTrace);
155
202
                                return CreateColorBlock ("#FF0000", size);
156
203
                        }
157
 
                        
 
204
 
 
205
                        // If this name refers to an icon defined in an extension point, the images for the icon will now be laoded
158
206
                        EnsureStockIconIsLoaded (name, size);
159
207
 
160
208
                        //if an icon name begins with '#', we assume it's a hex colour
161
209
                        if (name[0] == '#')
162
210
                                return CreateColorBlock (name, size);
163
 
                        
164
 
                        string stockid = InternalGetStockId (name, size);
 
211
 
 
212
                        // Converts an image spec into a real stock icon id
 
213
                        string stockid = GetStockIdForImageSpec (name, size);
 
214
 
165
215
                        if (string.IsNullOrEmpty (stockid)) {
166
216
                                LoggingService.LogWarning ("Can't get stock id for " + name + " : " + Environment.NewLine + Environment.StackTrace);
167
217
                                return CreateColorBlock ("#FF0000", size);
243
293
                                        LoadStockIcon (stockIcon[biggest], true);
244
294
                                        
245
295
                                }
 
296
                                // Icon loaded, it can be removed from the pending icon collection
246
297
                                iconStock.Remove (stockId);
247
298
                        }
248
299
                }
337
388
        
338
389
                public static Gtk.Image GetImage (string name, Gtk.IconSize size)
339
390
                {
340
 
                        return new Gtk.Image (GetPixbuf (name, size));
 
391
                        var img = new Gtk.Image ();
 
392
                        img.LoadIcon (name, size);
 
393
                        return img;
341
394
                }
342
395
                /*
343
396
                public static string GetStockIdFromResource (RuntimeAddin addin, string id)
364
417
                }
365
418
                public static string GetStockId (string filename, Gtk.IconSize iconSize)
366
419
                {
367
 
                        return InternalGetStockId (filename, iconSize);
 
420
                        return GetStockIdForImageSpec (filename, iconSize);
368
421
                }
369
422
                
370
423
                public static string GetStockId (RuntimeAddin addin, string filename)
373
426
                }
374
427
                public static string GetStockId (RuntimeAddin addin, string filename, Gtk.IconSize iconSize)
375
428
                {
376
 
                        return InternalGetStockId (addin, filename, iconSize);
 
429
                        return GetStockIdForImageSpec (addin, filename, iconSize);
377
430
                }
378
431
                
379
432
                static void AddToIconFactory (string stockId, Gdk.Pixbuf pixbuf, Gtk.IconSize iconSize)
392
445
                        iconSet.AddSource (source);
393
446
                }
394
447
 
 
448
                static void AddToAnimatedIconFactory (string stockId, AnimatedIcon aicon)
 
449
                {
 
450
                        animationFactory [stockId] = aicon;
 
451
                }
 
452
 
395
453
                static string InternalGetStockIdFromResource (RuntimeAddin addin, string id, Gtk.IconSize size)
396
454
                {
397
455
                        if (!id.StartsWith ("res:"))
413
471
                        return stockId;
414
472
                }
415
473
                
 
474
                static string InternalGetStockIdFromAnimation (RuntimeAddin addin, string id, Gtk.IconSize size)
 
475
                {
 
476
                        if (!id.StartsWith ("animation:"))
 
477
                                return id;
 
478
                        
 
479
                        id = id.Substring (10);
 
480
                        Dictionary<string, string> hash;
 
481
                        int addinId;
 
482
 
 
483
                        if (addin != null) {
 
484
                                addinId = GetAddinId (addin);
 
485
                                hash = addinIcons[addinId];
 
486
                        } else {
 
487
                                addinId = -1;
 
488
                                hash = iconSpecToStockId;
 
489
                        }
 
490
 
 
491
                        string stockId = "__asm" + addinId + "__" + id + "__" + size;
 
492
                        if (!hash.ContainsKey (stockId)) {
 
493
                                var aicon = new AnimatedIcon (addin, id, size);
 
494
                                AddToIconFactory (stockId, aicon.FirstFrame, size);
 
495
                                AddToAnimatedIconFactory (stockId, aicon);
 
496
                                hash[stockId] = stockId;
 
497
                        }
 
498
                        return stockId;
 
499
                }
 
500
 
416
501
                static int GetAddinId (RuntimeAddin addin)
417
502
                {
418
503
                        int result = addins.IndexOf (addin);
469
554
                        return res;
470
555
                }
471
556
                
472
 
                static string InternalGetStockId (string filename, Gtk.IconSize size)
 
557
                static string GetStockIdForImageSpec (string filename, Gtk.IconSize size)
473
558
                {
474
 
                        return InternalGetStockId (null, filename, size);
 
559
                        return GetStockIdForImageSpec (null, filename, size);
475
560
                }
476
561
 
477
 
                static string InternalGetStockId (RuntimeAddin addin, string filename, Gtk.IconSize size)
 
562
                static string GetStockIdForImageSpec (RuntimeAddin addin, string filename, Gtk.IconSize size)
478
563
                {
479
564
                        if (filename.IndexOf ('|') == -1)
480
565
                                return PrivGetStockId (addin, filename, size);
491
576
                        if (addin != null && filename.StartsWith ("res:"))
492
577
                                return InternalGetStockIdFromResource (addin, filename, size);
493
578
 
 
579
                        if (filename.StartsWith ("animation:"))
 
580
                                return InternalGetStockIdFromAnimation (addin, filename, size);
 
581
 
494
582
                        return filename;
495
583
                }
 
584
 
 
585
                public static bool IsAnimation (string iconId, Gtk.IconSize size)
 
586
                {
 
587
                        EnsureStockIconIsLoaded (iconId, size);
 
588
                        string id = GetStockIdForImageSpec (iconId, size);
 
589
                        return animationFactory.ContainsKey (id);
 
590
                }
 
591
 
 
592
                public static AnimatedIcon GetAnimatedIcon (string iconId)
 
593
                {
 
594
                        return GetAnimatedIcon (iconId, Gtk.IconSize.Button);
 
595
                }
 
596
 
 
597
                public static AnimatedIcon GetAnimatedIcon (string iconId, Gtk.IconSize size)
 
598
                {
 
599
                        EnsureStockIconIsLoaded (iconId, size);
 
600
                        string id = GetStockIdForImageSpec (iconId, size);
 
601
 
 
602
                        AnimatedIcon aicon;
 
603
                        animationFactory.TryGetValue (id, out aicon);
 
604
                        return aicon;
 
605
                }
 
606
 
 
607
                static List<WeakReference> animatedImages = new List<WeakReference> ();
 
608
 
 
609
                class AnimatedImageInfo {
 
610
                        public Gtk.Image Image;
 
611
                        public AnimatedIcon AnimatedIcon;
 
612
                        public IDisposable Animation;
 
613
 
 
614
                        public AnimatedImageInfo (Gtk.Image img, AnimatedIcon anim)
 
615
                        {
 
616
                                Image = img;
 
617
                                AnimatedIcon = anim;
 
618
                                img.Realized += HandleRealized;
 
619
                                img.Unrealized += HandleUnrealized;
 
620
                                img.Destroyed += HandleDestroyed;
 
621
                                if (img.IsRealized)
 
622
                                        StartAnimation ();
 
623
                        }
 
624
 
 
625
                        void StartAnimation ()
 
626
                        {
 
627
                                if (Animation == null) {
 
628
                                        Animation = AnimatedIcon.StartAnimation (delegate (Gdk.Pixbuf pix) {
 
629
                                                Image.Pixbuf = pix;
 
630
                                        });
 
631
                                }
 
632
                        }
 
633
 
 
634
                        void StopAnimation ()
 
635
                        {
 
636
                                if (Animation != null) {
 
637
                                        Animation.Dispose ();
 
638
                                        Animation = null;
 
639
                                }
 
640
                        }
 
641
 
 
642
                        void HandleDestroyed (object sender, EventArgs e)
 
643
                        {
 
644
                                UnregisterImageAnimation (this);
 
645
                        }
 
646
 
 
647
                        void HandleUnrealized (object sender, EventArgs e)
 
648
                        {
 
649
                                StopAnimation ();
 
650
                        }
 
651
 
 
652
                        void HandleRealized (object sender, EventArgs e)
 
653
                        {
 
654
                                StartAnimation ();
 
655
                        }
 
656
 
 
657
                        public void Dispose ()
 
658
                        {
 
659
                                StopAnimation ();
 
660
                                Image.Realized -= HandleRealized;
 
661
                                Image.Unrealized -= HandleUnrealized;
 
662
                                Image.Destroyed -= HandleDestroyed;
 
663
                        }
 
664
                }
 
665
 
 
666
                public static void LoadIcon (this Gtk.Image image, string iconId, Gtk.IconSize size)
 
667
                {
 
668
                        AnimatedImageInfo ainfo = animatedImages.Select (a => (AnimatedImageInfo) a.Target).FirstOrDefault (a => a != null && a.Image == image);
 
669
                        if (ainfo != null) {
 
670
                                if (ainfo.AnimatedIcon.AnimationSpec == iconId)
 
671
                                        return;
 
672
                                UnregisterImageAnimation (ainfo);
 
673
                        }
 
674
                        if (IsAnimation (iconId, size)) {
 
675
                                var anim = GetAnimatedIcon (iconId);
 
676
                                ainfo = new AnimatedImageInfo (image, anim);
 
677
                                ainfo.Animation = anim.StartAnimation (delegate (Gdk.Pixbuf pix) {
 
678
                                        image.Pixbuf = pix;
 
679
                                });
 
680
                                animatedImages.Add (new WeakReference (ainfo));
 
681
                        } else
 
682
                                image.Pixbuf = GetPixbuf (iconId, size);
 
683
                }
 
684
 
 
685
                static void UnregisterImageAnimation (AnimatedImageInfo ainfo)
 
686
                {
 
687
                        ainfo.Dispose ();
 
688
                        animatedImages.RemoveAll (a => (AnimatedImageInfo)a.Target == ainfo);
 
689
                }
496
690
        }
 
691
 
497
692
}