diff --git a/BasicSccProvider.csproj b/BasicSccProvider.csproj index 75efb42..238b052 100644 --- a/BasicSccProvider.csproj +++ b/BasicSccProvider.csproj @@ -134,6 +134,7 @@ True Resources.resx + Component @@ -183,6 +184,7 @@ + diff --git a/GitApi/GitFileStatus.cs b/GitApi/GitFileStatus.cs index ed457d3..c4a7d26 100644 --- a/GitApi/GitFileStatus.cs +++ b/GitApi/GitFileStatus.cs @@ -16,6 +16,7 @@ public enum GitFileStatus Added, Deleted, Conflict, + Merged, Ignored, Renamed, Copied diff --git a/GitSccOptions.cs b/GitSccOptions.cs index 38b40f8..e4d3bcc 100644 --- a/GitSccOptions.cs +++ b/GitSccOptions.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; +using System.Diagnostics; using System.IO; using System.Xml.Serialization; using Microsoft.VisualStudio.Shell; @@ -31,6 +29,7 @@ public class GitSccOptions private static GitSccOptions gitSccOptions; + [DebuggerBrowsable(DebuggerBrowsableState.Never)] public static GitSccOptions Current { get @@ -43,6 +42,24 @@ public static GitSccOptions Current } } + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + public static bool IsVisualStudio2010 + { + get + { + return !IsVisualStudio2012 && BasicSccProvider.GetGlobalService(typeof(SVsSolution)) is IVsSolution4; + } + } + + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + public static bool IsVisualStudio2012 + { + get + { + return BasicSccProvider.GetGlobalService(typeof(SVsDifferenceService)) != null; + } + } + private GitSccOptions() { diff --git a/Resources.Designer.cs b/Resources.Designer.cs index c28e73e..3b33478 100644 --- a/Resources.Designer.cs +++ b/Resources.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.17929 +// Runtime Version:4.0.30319.18034 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. @@ -153,5 +153,15 @@ internal static System.Drawing.Bitmap SccGlyphs { return ((System.Drawing.Bitmap)(obj)); } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SccGlyphs2012 { + get { + object obj = ResourceManager.GetObject("SccGlyphs2012", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/Resources.resx b/Resources.resx index 27ddfa9..995d1f2 100644 --- a/Resources.resx +++ b/Resources.resx @@ -148,4 +148,7 @@ Git History + + resources\SccGlyphs2012.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/Resources/SccGlyphs2012.png b/Resources/SccGlyphs2012.png new file mode 100644 index 0000000..c9f709d Binary files /dev/null and b/Resources/SccGlyphs2012.png differ diff --git a/SccGlyphsHelper.cs b/SccGlyphsHelper.cs new file mode 100644 index 0000000..1d72e5d --- /dev/null +++ b/SccGlyphsHelper.cs @@ -0,0 +1,163 @@ +namespace GitScc +{ + using Color = System.Drawing.Color; + using Image = System.Drawing.Image; + using ImageList = System.Windows.Forms.ImageList; + using Size = System.Drawing.Size; + using VsStateIcon = Microsoft.VisualStudio.Shell.Interop.VsStateIcon; + + internal static class SccGlyphsHelper + { + // Remember the base index where our custom scc glyph start + private static uint _customSccGlyphBaseIndex = 0; + + // Our custom image list + private static ImageList _customSccGlyphsImageList; + + // Indexes of icons in our custom image list + private enum CustomSccGlyphs2010 + { + Untracked = 0, + Staged = 1, + Modified = 2, + Tracked = 3, + }; + + // Indexes of icons in our custom image list + private enum CustomSccGlyphs2012 + { + New = 0, + Staged = 1, + Conflicted = 2, + Merged = 3, + }; + + public static VsStateIcon Tracked + { + get + { + if (GitSccOptions.IsVisualStudio2010 && GitSccOptions.Current.UseTGitIconSet) + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2010.Tracked); + + return VsStateIcon.STATEICON_CHECKEDIN; + } + } + + public static VsStateIcon Modified + { + get + { + if (GitSccOptions.IsVisualStudio2010 && GitSccOptions.Current.UseTGitIconSet) + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2010.Modified); + + return VsStateIcon.STATEICON_CHECKEDOUT; + } + } + + public static VsStateIcon New + { + get + { + if (GitSccOptions.IsVisualStudio2010) + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2010.Untracked); + + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2012.New); + } + } + + public static VsStateIcon Added + { + get + { + return Staged; + } + } + + public static VsStateIcon Staged + { + get + { + if (GitSccOptions.IsVisualStudio2010) + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2010.Staged); + + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2012.Staged); + } + } + + public static VsStateIcon NotControlled + { + get + { + return VsStateIcon.STATEICON_NOSTATEICON; + } + } + + public static VsStateIcon Ignored + { + get + { + return VsStateIcon.STATEICON_EXCLUDEDFROMSCC; + } + } + + public static VsStateIcon Conflict + { + get + { + if (GitSccOptions.IsVisualStudio2010) + return VsStateIcon.STATEICON_DISABLED; + + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2012.Conflicted); + } + } + + public static VsStateIcon Merged + { + get + { + if (GitSccOptions.IsVisualStudio2010) + return Modified; + + return (VsStateIcon)(_customSccGlyphBaseIndex + (uint)CustomSccGlyphs2012.Merged); + } + } + + public static VsStateIcon Default + { + get + { + return VsStateIcon.STATEICON_NOSTATEICON; + } + } + + public static uint GetCustomGlyphList(uint baseIndex) + { + // If this is the first time we got called, construct the image list, remember the index, etc + if (_customSccGlyphsImageList == null) + { + // The shell calls this function when the provider becomes active to get our custom glyphs + // and to tell us what's the first index we can use for our glyphs + // Remember the index in the scc glyphs (VsStateIcon) where our custom glyphs will start + _customSccGlyphBaseIndex = baseIndex; + + // Create a new imagelist + _customSccGlyphsImageList = new ImageList(); + + // Set the transparent color for the imagelist (the SccGlyphs.bmp uses magenta for background) + _customSccGlyphsImageList.TransparentColor = Color.FromArgb(255, 0, 255); + + // Set the corret imagelist size (7x16 pixels, otherwise the system will either stretch the image or fill in with black blocks) + _customSccGlyphsImageList.ImageSize = new Size(7, 16); + + // Add the custom scc glyphs we support to the list + // NOTE: VS2005 and VS2008 are limited to 4 custom scc glyphs (let's hope this will change in future versions) + Image sccGlyphs = GitSccOptions.IsVisualStudio2010 ? Resources.SccGlyphs : Resources.SccGlyphs2012; + _customSccGlyphsImageList.Images.AddStrip(sccGlyphs); + } + + // Return a Win32 HIMAGELIST handle to our imagelist to the shell (by keeping the ImageList a member of the class we guarantee the Win32 object is still valid when the shell needs it) + return (uint)_customSccGlyphsImageList.Handle; + + } + } +} diff --git a/SccProviderOptionsControl.cs b/SccProviderOptionsControl.cs index 6ec1f84..4a57f14 100644 --- a/SccProviderOptionsControl.cs +++ b/SccProviderOptionsControl.cs @@ -357,6 +357,7 @@ private void SccProviderOptionsControl_Load(object sender, EventArgs e) this.checkBox1.Checked = GitSccOptions.Current.NotExpandGitExtensions; this.checkBox2.Checked = GitSccOptions.Current.NotExpandTortoiseGit; this.checkBox3.Checked = GitSccOptions.Current.UseTGitIconSet; + this.checkBox3.Enabled = GitSccOptions.IsVisualStudio2010; this.checkBox4.Checked = GitSccOptions.Current.DisableAutoRefresh; this.checkBox5.Checked = GitSccOptions.Current.DisableAutoLoad; this.checkBox6.Checked = GitSccOptions.Current.NotUseUTF8FileNames; @@ -402,7 +403,7 @@ internal void Save() GitSccOptions.Current.TortoiseGitPath = this.textBox4.Text; GitSccOptions.Current.NotExpandGitExtensions = this.checkBox1.Checked; GitSccOptions.Current.NotExpandTortoiseGit = this.checkBox2.Checked; - GitSccOptions.Current.UseTGitIconSet = this.checkBox3.Checked; + GitSccOptions.Current.UseTGitIconSet = GitSccOptions.IsVisualStudio2010 && this.checkBox3.Checked; GitSccOptions.Current.DisableAutoRefresh = this.checkBox4.Checked; GitSccOptions.Current.DisableAutoLoad = this.checkBox5.Checked; GitSccOptions.Current.NotUseUTF8FileNames = this.checkBox6.Checked; diff --git a/SccProviderService.cs b/SccProviderService.cs index 4a24fcb..835120c 100644 --- a/SccProviderService.cs +++ b/SccProviderService.cs @@ -183,45 +183,46 @@ public int GetSccGlyph([InAttribute] int cFiles, [InAttribute] string[] rgpszFul switch (status) { case GitFileStatus.Tracked: - rgsiGlyphs[i] = GitSccOptions.Current.UseTGitIconSet ? - (VsStateIcon)(this._customSccGlyphBaseIndex + (uint)CustomSccGlyphs.Tracked) : - VsStateIcon.STATEICON_CHECKEDIN; + rgsiGlyphs[i] = SccGlyphsHelper.Tracked; sccStatus = __SccStatus.SCC_STATUS_CONTROLLED; break; case GitFileStatus.Modified: - rgsiGlyphs[i] = GitSccOptions.Current.UseTGitIconSet ? - (VsStateIcon)(this._customSccGlyphBaseIndex + (uint)CustomSccGlyphs.Modified) : - VsStateIcon.STATEICON_CHECKEDOUT; + rgsiGlyphs[i] = SccGlyphsHelper.Modified; sccStatus = __SccStatus.SCC_STATUS_CONTROLLED | __SccStatus.SCC_STATUS_CHECKEDOUT | __SccStatus.SCC_STATUS_OUTBYUSER; break; case GitFileStatus.New: - rgsiGlyphs[i] = (VsStateIcon)(this._customSccGlyphBaseIndex + (uint)CustomSccGlyphs.Untracked); + rgsiGlyphs[i] = SccGlyphsHelper.New; sccStatus = __SccStatus.SCC_STATUS_CONTROLLED | __SccStatus.SCC_STATUS_CHECKEDOUT | __SccStatus.SCC_STATUS_OUTBYUSER; break; case GitFileStatus.Added: case GitFileStatus.Staged: - rgsiGlyphs[i] = (VsStateIcon)(this._customSccGlyphBaseIndex + (uint)CustomSccGlyphs.Staged); + rgsiGlyphs[i] = status == GitFileStatus.Added ? SccGlyphsHelper.Added : SccGlyphsHelper.Staged; sccStatus = __SccStatus.SCC_STATUS_CONTROLLED | __SccStatus.SCC_STATUS_CHECKEDOUT | __SccStatus.SCC_STATUS_OUTBYUSER; break; case GitFileStatus.NotControlled: - rgsiGlyphs[i] = VsStateIcon.STATEICON_NOSTATEICON; + rgsiGlyphs[i] = SccGlyphsHelper.NotControlled; sccStatus = __SccStatus.SCC_STATUS_NOTCONTROLLED; break; case GitFileStatus.Ignored: - rgsiGlyphs[i] = VsStateIcon.STATEICON_EXCLUDEDFROMSCC; + rgsiGlyphs[i] = SccGlyphsHelper.Ignored; sccStatus = __SccStatus.SCC_STATUS_NOTCONTROLLED; break; case GitFileStatus.Conflict: - rgsiGlyphs[i] = VsStateIcon.STATEICON_DISABLED; + rgsiGlyphs[i] = SccGlyphsHelper.Conflict; sccStatus = __SccStatus.SCC_STATUS_CONTROLLED | __SccStatus.SCC_STATUS_CHECKEDOUT | __SccStatus.SCC_STATUS_OUTBYUSER | __SccStatus.SCC_STATUS_MERGED; break; + case GitFileStatus.Merged: + rgsiGlyphs[i] = SccGlyphsHelper.Merged; + sccStatus = __SccStatus.SCC_STATUS_CONTROLLED | __SccStatus.SCC_STATUS_CHECKEDOUT | __SccStatus.SCC_STATUS_OUTBYUSER; + break; + default: sccStatus = __SccStatus.SCC_STATUS_INVALID; break; @@ -361,50 +362,10 @@ public int OnAfterMergeSolution([InAttribute] Object pUnkReserved) #region IVsSccGlyphs Members - // Remember the base index where our custom scc glyph start - private uint _customSccGlyphBaseIndex = 0; - // Our custom image list - ImageList _customSccGlyphsImageList; - // Indexes of icons in our custom image list - enum CustomSccGlyphs - { - Untracked = 0, - Staged = 1, - Modified = 2, - Tracked = 3, - }; - public int GetCustomGlyphList(uint BaseIndex, out uint pdwImageListHandle) { - // If this is the first time we got called, construct the image list, remember the index, etc - if (this._customSccGlyphsImageList == null) - { - // The shell calls this function when the provider becomes active to get our custom glyphs - // and to tell us what's the first index we can use for our glyphs - // Remember the index in the scc glyphs (VsStateIcon) where our custom glyphs will start - this._customSccGlyphBaseIndex = BaseIndex; - - // Create a new imagelist - this._customSccGlyphsImageList = new ImageList(); - - // Set the transparent color for the imagelist (the SccGlyphs.bmp uses magenta for background) - this._customSccGlyphsImageList.TransparentColor = Color.FromArgb(255, 0, 255); - - // Set the corret imagelist size (7x16 pixels, otherwise the system will either stretch the image or fill in with black blocks) - this._customSccGlyphsImageList.ImageSize = new Size(7, 16); - - // Add the custom scc glyphs we support to the list - // NOTE: VS2005 and VS2008 are limited to 4 custom scc glyphs (let's hope this will change in future versions) - Image sccGlyphs = (Image)Resources.SccGlyphs; - this._customSccGlyphsImageList.Images.AddStrip(sccGlyphs); - } - - // Return a Win32 HIMAGELIST handle to our imagelist to the shell (by keeping the ImageList a member of the class we guarantee the Win32 object is still valid when the shell needs it) - pdwImageListHandle = (uint)this._customSccGlyphsImageList.Handle; - - // Return success (If you don't want to have custom glyphs return VSConstants.E_NOTIMPL) + pdwImageListHandle = SccGlyphsHelper.GetCustomGlyphList(BaseIndex); return VSConstants.S_OK; - } #endregion