public FileInfo(ProjectInfo project, string name, uint itemid) { _name = name; _itemid = itemid; _icon = VsStateIcon.STATEICON_CHECKEDOUT; _project = project; }
//TODO Move TO Provider /// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> public async Task RefreshNodesGlyphs(IList <VSITEMSELECTION> selectedNodes) { foreach (VSITEMSELECTION vsItemSel in selectedNodes) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsSccProject2 sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = await GetSolutionFileName(); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = await _sccProvider.GetServiceAsync(typeof(SVsSolution)) as IVsHierarchy; solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyph() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); } } else { // It may be easier/faster to simply refresh all the nodes in the project, // and let the project call back on GetSccGlyph, but just for the sake of the demo, // let's refresh ourselves only one node at a time IList <string> sccFiles = await GetNodeFiles(sccProject2, vsItemSel.itemid); // We'll use for the node glyph just the Master file's status (ignoring special files of the node) if (sccFiles.Count > 0) { string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = sccFiles[0]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[1]; rguiAffectedNodes[0] = vsItemSel.itemid; sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } } }
public void GlyphChanged(VsStateIcon icon) { int hr; _icon = icon; if (ErrorHandler.Failed(hr = _project.SccProject.SccGlyphChanged(1, new[] { ItemId }, new[] { icon }, new uint[0]))) { TestSccProvider.Fail("Bad HR from SccGlyphChanged: {0}", hr); } }
public int SccGlyphChanged(int cAffectedNodes, uint[] rgitemidAffectedNodes, VsStateIcon[] rgsiNewGlyphs, uint[] rgdwNewSccStatus) { IVsSccManager2 sccService = _context.GetService <IVsSccManager2>(typeof(SVsSccManager)); string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = GetSolutionFileName(_context); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; sccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = (IVsHierarchy)_context.GetService(typeof(SVsSolution)); return(solHier.SetProperty(VSItemId.Root, (int)__VSHPROPID.VSHPROPID_StateIconIndex, (int)rgsiGlyphs[0])); }
public int GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { for (int i = 0; i < cFiles; i++) { bool found = false; foreach (var proj in _loadedProjects.Values) { FileInfo fi; if (proj.Files.TryGetValue(rgpszFullPaths[i], out fi)) { rgsiGlyphs[i] = fi.StateIcon; found = true; } } if (!found) { rgsiGlyphs[i] = VsStateIcon.STATEICON_CHECKEDOUT; } } return VSConstants.S_OK; }
private async Task RefreshSolutionGlyphs() { await ThreadHelper.JoinableTaskFactory.RunAsync(VsTaskRunContext.UIThreadBackgroundPriority, async delegate { // On caller's thread. Switch to main thread (if we're not already there). await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Now on UI thread via background priority. await Task.Yield(); string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = await GetSolutionFileName(); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = (IVsHierarchy)_sccProvider.GetService(typeof(SVsSolution)); solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); }); }
internal void ForceGlyphChanges() { ThreadHelper.ThrowIfNotOnUIThread(); uint[] idsArray; string[] namesArray; { List <uint> ids = new List <uint>(_files.Count); List <string> names = new List <string>(_files.Count); foreach (SccProjectFileReference r in _files) { uint id = r.ProjectItemId; if (id == VSItemId.Nil) { continue; } string name = r.ProjectFile.FullPath; if (string.IsNullOrEmpty(name)) { continue; } ids.Add(id); names.Add(name); } idsArray = ids.ToArray(); namesArray = names.ToArray(); } VsStateIcon[] newGlyphs = new VsStateIcon[idsArray.Length]; uint[] sccState = new uint[idsArray.Length]; if (VSErr.Succeeded(Map.GetSccGlyph(namesArray, newGlyphs, sccState))) { SccProject.SccGlyphChanged(idsArray.Length, idsArray, newGlyphs, sccState); } }
private void getFileSscStatus(ProjectItems projectItems, IVsSccManager2 sscMgr) { if (projectItems == null || projectItems.Count == 0) { return; } foreach (ProjectItem item in projectItems) { if (item.Properties != null) { Property fullName = item.Properties.Item("FullPath"); if (fullName != null) { VsStateIcon[] icons = new VsStateIcon[1]; uint[] status = new uint[1]; if (VSConstants.S_OK == sscMgr.GetSccGlyph(1, new[] { fullName.Value.ToString() }, icons, status)) { Debug.WriteLine(string.Format("status {0} - file {1}", status[0], fullName.Value)); } } } getFileSscStatus(item.ProjectItems, sscMgr); } }
public async Task QuickRefreshNodesGlyphs(IVsSccProject2 project, List <string> files) { try { if (files.Count > 0) { string[] rgpszFullPaths = new string[files.Count]; for (int i = 0; i < files.Count; i++) { rgpszFullPaths[i] = files[i]; } VsStateIcon[] rgsiGlyphs = new VsStateIcon[files.Count]; uint[] rgdwSccStatus = new uint[files.Count]; GetSccGlyph(files.Count, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[files.Count]; //TODO We could/Should cache this mapping !!!! await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IList <uint> subnodes = await SolutionExtensions.GetProjectItems((IVsHierarchy)project, VSConstants.VSITEMID_ROOT); var dict = new Dictionary <string, uint>(); var proj = project as IVsProject2; foreach (var id in subnodes) { string docname; var res = proj.GetMkDocument(id, out docname); if (res == VSConstants.S_OK && !string.IsNullOrEmpty(docname)) { dict[docname] = id; } } for (int i = 0; i < files.Count; ++i) { uint id; if (dict.TryGetValue(files[i], out id)) { rguiAffectedNodes[i] = id; } } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); project.SccGlyphChanged(files.Count, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } catch (Exception ex) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsActivityLog log = _sccProvider.GetService(typeof(SVsActivityLog)) as IVsActivityLog; if (log == null) { return; } int hr = log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, ex.StackTrace, string.Format(CultureInfo.CurrentCulture, "Called for: {0}", this.ToString())); } }
int IVsSccManager2.GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { if (cFiles == 0 || String.IsNullOrEmpty(rgpszFullPaths[0])) { return VSConstants.S_OK; } rgsiGlyphs[0] = GetStatusIcon(rgpszFullPaths[0]); return VSConstants.S_OK; }
public void TestFileStatus() { SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); VsStateIcon [] rgsiGlyphs = new VsStateIcon[1]; VsStateIcon [] rgsiGlyphsFromStatus = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; int result = 0; string strTooltip; // Check glyphs and statuses for uncontrolled items IList <string> files = new string[] { solution.SolutionFile, project.ProjectFile, project.ProjectItems[0] }; foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_BLANK, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_NOTCONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Uncontrolled items should not have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length == 0); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked in items should have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckoutFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedOut, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked out items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckinFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); } // Add a new file to the project (don't worry about TPD events for now) string pendingAddFile = Path.GetTempFileName(); project.AddItem(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); // Pending add items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, 1, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual <int>(VSConstants.S_OK, result); Assert.AreEqual <VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual <uint>((uint)__SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); }
public int SccGlyphChanged(int cAffectedNodes, uint[] rgitemidAffectedNodes, VsStateIcon[] rgsiNewGlyphs, uint[] rgdwNewSccStatus) { IVsSccManager2 sccService = _context.GetService<IVsSccManager2>(typeof(SVsSccManager)); string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = GetSolutionFileName(_context); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; sccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = (IVsHierarchy)_context.GetService(typeof(SVsSolution)); return solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); }
public int GetSccGlyphFromStatus(uint dwSccStatus, VsStateIcon[] psiGlyph) { psiGlyph[0] = VsStateIcon.STATEICON_BLANK; return VSConstants.S_OK; }
//TODO Move TO Provider /// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> public async Task RefreshNodesGlyphs(IList<VSITEMSELECTION> selectedNodes) { foreach (VSITEMSELECTION vsItemSel in selectedNodes) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsSccProject2 sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = await GetSolutionFileName(); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy IVsHierarchy solHier = (IVsHierarchy)_sccProvider.GetService(typeof(SVsSolution)); solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyph() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); } } else { // It may be easier/faster to simply refresh all the nodes in the project, // and let the project call back on GetSccGlyph, but just for the sake of the demo, // let's refresh ourselves only one node at a time IList<string> sccFiles = await GetNodeFiles(sccProject2, vsItemSel.itemid); // We'll use for the node glyph just the Master file's status (ignoring special files of the node) if (sccFiles.Count > 0) { string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = sccFiles[0]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[1]; rguiAffectedNodes[0] = vsItemSel.itemid; sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } } }
public int GetSccGlyphFromStatus(uint dwSccStatus, VsStateIcon[] psiGlyph) { return VSConstants.S_OK; }
private void UpdateNode(VSITEMSELECTION vsItemSel) { try { var sccProject2 = vsItemSel.pHier as IVsSccProject2; var rgpszFullPaths = new string[1]; vsItemSel.pHier.GetCanonicalName(vsItemSel.itemid, out rgpszFullPaths[0]); var rgsiGlyphs = new VsStateIcon[1]; var rgdwSccStatus = new uint[1]; this.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); var rguiAffectedNodes = new uint[] { vsItemSel.itemid }; sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } catch (Exception e) { e.ToString(); } }
/// <summary> /// This method is called by projects to discover the source control glyphs /// to use on files and the files' source control status; this is the only way to get status. /// </summary> /// <param name="cFiles">The c files.</param> /// <param name="rgpszFullPaths">The RGPSZ full paths.</param> /// <param name="rgsiGlyphs">The rgsi glyphs.</param> /// <param name="rgdwSccStatus">The RGDW SCC status.</param> /// <returns></returns> public int GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { if (rgpszFullPaths == null || rgsiGlyphs == null) return VSConstants.E_POINTER; // Documented as impossible if (!_active) { for (int i = 0; i < cFiles; i++) { rgsiGlyphs[i] = VsStateIcon.STATEICON_NOSTATEICON; if(rgdwSccStatus != null) rgdwSccStatus[i] = (uint)SccStatus.SCC_STATUS_NOTCONTROLLED; } return VSConstants.S_OK; } for (int i = 0; i < cFiles; i++) { string file = rgpszFullPaths[i]; if (!IsSafeSccPath(file)) { rgsiGlyphs[i] = VsStateIcon.STATEICON_BLANK; if (rgdwSccStatus != null) rgdwSccStatus[i] = (uint)SccStatus.SCC_STATUS_NOTCONTROLLED; continue; } AnkhGlyph glyph = GetPathGlyph(file); if (rgsiGlyphs != null) rgsiGlyphs[i] = (VsStateIcon)glyph; if (rgdwSccStatus != null) { // This will make VS use the right texts on refactor, replace, etc. rgdwSccStatus[i] = GlyphToStatus(glyph); } } return VSConstants.S_OK; }
/// <summary> /// This method is called by the source control portion of the environment to inform the project of changes to the source control glyph on various nodes. /// </summary> /// <param name="affectedNodes">Count of changed nodes.</param> /// <param name="itemidAffectedNodes">An array of VSITEMID identifiers of the changed nodes.</param> /// <param name="newGlyphs">An array of VsStateIcon glyphs representing the new state of the corresponding item in rgitemidAffectedNodes.</param> /// <param name="newSccStatus">An array of status flags from SccStatus corresponding to rgitemidAffectedNodes. </param> /// <returns>If the method succeeds, it returns S_OK. If it fails, it returns an error code. </returns> public virtual int SccGlyphChanged(int affectedNodes, uint[] itemidAffectedNodes, VsStateIcon[] newGlyphs, uint[] newSccStatus) { // if all the paramaters are null adn the count is 0, it means scc wants us to updated everything if (affectedNodes == 0 && itemidAffectedNodes == null && newGlyphs == null && newSccStatus == null) { this.ReDraw(UIHierarchyElement.SccState); this.UpdateSccStateIcons(); } else if (affectedNodes > 0 && itemidAffectedNodes != null && newGlyphs != null && newSccStatus != null) { for (int i = 0; i < affectedNodes; i++) { HierarchyNode n = this.NodeFromItemId(itemidAffectedNodes[i]); if (n == null) { throw new ArgumentException(SR.GetString(SR.InvalidParameter, CultureInfo.CurrentUICulture), "itemidAffectedNodes"); } n.ReDraw(UIHierarchyElement.SccState); } } return VSConstants.S_OK; }
int IVsSccManager2.GetSccGlyphFromStatus(uint dwSccStatus, VsStateIcon[] psiGlyph) { return VSConstants.S_OK; }
public int GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { if (!_active) { rgsiGlyphs.Fill(VsStateIcon.STATEICON_NOSTATEICON); if (rgdwSccStatus != null) rgdwSccStatus.Fill((uint)__SccStatus.SCC_STATUS_NOTCONTROLLED); return VSConstants.S_OK; } // TODO: Set the status to something more meaningful if (rgdwSccStatus != null) rgdwSccStatus[0] = (uint)(_active ? __SccStatus.SCC_STATUS_CONTROLLED : __SccStatus.SCC_STATUS_NOTCONTROLLED); var status = _repositoryService.Status.GetStatusOf(rgpszFullPaths[0]); var fileStatus = status == null ? FileStatus.NotModified : status.FileStatus; // TODO: Handle status combinations properly // For now, if a file status is a combination of modified and something else, // we treat it as modified if ((fileStatus & FileStatus.Modified) != 0) fileStatus = FileStatus.Modified; switch (fileStatus) { case FileStatus.Untracked: rgsiGlyphs[0] = VsStateIcon.STATEICON_BLANK; break; case FileStatus.NotModified: rgsiGlyphs[0] = VsStateIcon.STATEICON_CHECKEDIN; break; case FileStatus.Added: rgsiGlyphs[0] = VsStateIcon.STATEICON_EDITABLE; break; case FileStatus.Modified: rgsiGlyphs[0] = VsStateIcon.STATEICON_CHECKEDOUT; break; case FileStatus.Ignored: rgsiGlyphs[0] = VsStateIcon.STATEICON_EXCLUDEDFROMSCC; break; case FileStatus.Removed: rgsiGlyphs[0] = VsStateIcon.STATEICON_ORPHANED; break; case FileStatus.Conflicted: rgsiGlyphs[0] = VsStateIcon.STATEICON_DISABLED; break; default: if (rgdwSccStatus != null) rgdwSccStatus[0] = (uint)__SccStatus.SCC_STATUS_NOTCONTROLLED; rgsiGlyphs[0] = VsStateIcon.STATEICON_NOSTATEICON; break; } return VSConstants.S_OK; }
public void TestFileStatus() { SccProviderService target = GetSccProviderServiceInstance; solution.SolutionFile = Path.GetTempFileName(); MockIVsProject project = new MockIVsProject(Path.GetTempFileName()); project.AddItem(Path.GetTempFileName()); solution.AddProject(project); VsStateIcon [] rgsiGlyphs = new VsStateIcon[1]; VsStateIcon [] rgsiGlyphsFromStatus = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; int result = 0; string strTooltip; // Check glyphs and statuses for uncontrolled items IList<string> files = new string[] { solution.SolutionFile, project.ProjectFile, project.ProjectItems[0] }; foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_BLANK, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_NOTCONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Uncontrolled items should not have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length == 0); Hashtable uncontrolled = new Hashtable(); uncontrolled[project as IVsSccProject2] = true; target.AddProjectsToSourceControl(ref uncontrolled, true); foreach (string file in files) { Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked in items should have tooltips target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckoutFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedOut, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); result = target.GetSccGlyphFromStatus(rgdwSccStatus[0], rgsiGlyphsFromStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(rgsiGlyphs[0], rgsiGlyphsFromStatus[0]); } // Checked out items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, VSConstants.VSITEMID_ROOT, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); foreach (string file in files) { target.CheckinFile(file); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(file), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { file }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); } // Add a new file to the project (don't worry about TPD events for now) string pendingAddFile = Path.GetTempFileName(); project.AddItem(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsUncontrolled, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDOUT, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CHECKEDOUT, rgdwSccStatus[0]); // Pending add items should have tooltips, too target.GetGlyphTipText(project as IVsHierarchy, 1, out strTooltip); Assert.IsTrue(strTooltip.Length > 0); // Checkin the pending add file target.AddFileToSourceControl(pendingAddFile); Assert.AreEqual(SourceControlStatus.scsCheckedIn, target.GetFileStatus(pendingAddFile), "Incorrect status returned"); result = target.GetSccGlyph(1, new string[] { pendingAddFile }, rgsiGlyphs, rgdwSccStatus); Assert.AreEqual<int>(VSConstants.S_OK, result); Assert.AreEqual<VsStateIcon>(VsStateIcon.STATEICON_CHECKEDIN, rgsiGlyphs[0]); Assert.AreEqual<uint>((uint) __SccStatus.SCC_STATUS_CONTROLLED, rgdwSccStatus[0]); }
/// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> private void SyncAsyncRefreshNodesGlyphs(object parm) { RefreshNodesGlyphsArgs parms = parm as RefreshNodesGlyphsArgs; if (parms == null) { return; } IList <VSITEMSELECTION> selectedNodes = parms.selectedNodes; IList <string> files = parms.files; if (SccService.IsSolutionSelected) { selectedNodes = null; } P4VsProvider.Instance.ResetCommandStatus(); if (!P4VsProvider.Instance.IsThereASolution()) { return; } // make sure the context menus update for the new state P4VsProvider.Instance.ResetCommandStatus(); if (selectedNodes == null) { bool TreatProjectsAsFolders = Preferences.LocalSettings.GetBool("TreatProjectsAsFolders", true); if (TreatProjectsAsFolders) { string slnPath = Path.GetDirectoryName(P4VsProvider.Instance.GetSolutionFileName()); slnPath = string.Format("{0}\\...", slnPath); files = new List <string>(); files.Add(slnPath); } else { files = P4VsProvider.Instance.GetSolutionFiles(); } selectedNodes = new List <VSITEMSELECTION>(); IList <IVsHierarchy> controlledProjects = SccService.GetControlledProjects(); if (controlledProjects != null) { foreach (IVsHierarchy node in controlledProjects) { VSITEMSELECTION vsItem; vsItem.itemid = VSConstants.VSITEMID_ROOT; vsItem.pHier = node; selectedNodes.Add(vsItem); } } } if (SccService.ScmProvider != null) { if ((files != null) && (files.Count > 0)) { if (Preferences.LocalSettings.GetBool("LazyLoadStatus", false) == false) { SccService.ScmProvider.UpdateFiles(files, true); } foreach (string file in files) { if ((file.EndsWith("\\...")) || (file.EndsWith("\\*"))) { //wildcard SccService.ScmProvider.ResetIgnoredFilesMap(); break; } SccService.ScmProvider.ResetIgnoredFilesMap(file); } } else { SccService.ScmProvider.ResetIgnoredFilesMap(); } } foreach (VSITEMSELECTION vsItemSel in selectedNodes) { IVsSccProject2 sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { string name = ""; if (vsItemSel.pHier != null) { vsItemSel.pHier.GetCanonicalName(vsItemSel.itemid, out name); } if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = P4VsProvider.Instance.GetSolutionFileName(); VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; if (SccService.ScmProvider != null) { SccService.ScmProvider.UpdateFileInCache(rgpszFullPaths[0], true); } SccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { if ((SccService.UiDispatcher != null) && (SccService.UiDispatcher.Thread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId)) { SccService.UiDispatcher.BeginInvoke( new SccGlyphChangedDelegate(SccGlyphChanged), sccProject2, 0, null, null, null); } else { sccProject2.SccGlyphChanged(0, null, null, null); } } } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyphs() // with the files for each node that will need new glyph //sccProject2.SccGlyphChanged(0,null,null,null); // It may be easier/faster to simply refresh all the nodes in the project, // and let the project call back on GetSccGlyphs, but just for the sake of the demo, // let's refresh ourselves only one node at a time IList <string> sccFiles = P4VsProvider.Instance.GetNodeFiles(sccProject2, vsItemSel.itemid); //// We'll use for the node glyph just the Master file's status (ignoring special files of the node) if (sccFiles.Count > 0) { for (int idx = 0; idx < sccFiles.Count; idx++) { string[] rgpszFullPaths = new string[1]; rgpszFullPaths[0] = sccFiles[idx]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[1]; uint[] rgdwSccStatus = new uint[1]; if ((SccService.ScmProvider != null) && (files == null) || (files.Count <= 0)) { // update if not already updated SccService.ScmProvider.UpdateFileInCache(sccFiles[idx], true); } SccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[1]; if (idx == 0) { rguiAffectedNodes[0] = vsItemSel.itemid; if (sccProject2 != null) { // Don't async update the node's glyph if the new status is deleted // The mode might not exist anymore when the update is actually run if ((SccService.UiDispatcher != null) && (SccService.UiDispatcher.Thread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId) && ((rgdwSccStatus[0] & (uint)__SccStatus.SCC_STATUS_DELETED) == 0)) { SccService.UiDispatcher.BeginInvoke( new SccGlyphChangedDelegate(SccGlyphChanged), sccProject2, 1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } else { sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } } else { uint itemid; int fFound; IVsProject pscp = sccProject2 as IVsProject; VSDOCUMENTPRIORITY[] prio = new VSDOCUMENTPRIORITY[1]; if (pscp != null && pscp.IsDocumentInProject(sccFiles[idx], out fFound, prio, out itemid) == VSConstants.S_OK && fFound != 0) { rguiAffectedNodes[0] = itemid; // Don't async update the node's glyph if the new status is deleted // The mode might not exist anymore when the update is actually run if ((SccService.UiDispatcher != null) && (SccService.UiDispatcher.Thread.ManagedThreadId != Thread.CurrentThread.ManagedThreadId) && ((rgdwSccStatus[0] & (uint)__SccStatus.SCC_STATUS_DELETED) == 0)) { SccService.UiDispatcher.BeginInvoke( new SccGlyphChangedDelegate(SccGlyphChanged), sccProject2, 1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } else { sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } } } } else { // could not find files based on the nodes selected, so use the list of files passed in SccService.RefreshProjectGlyphs(files, true); } } } }
private void RefreshSourceControlGlyphs(VSITEMSELECTION node) { var project = node.pHier as IVsSccProject2; if (project != null) { // Refresh all the glyphs in the project; the project will call back GetSccGlyphs() // with the files for each node that will need new glyph project.SccGlyphChanged(0, null, null, null); } else if (node.itemid == VSConstants.VSITEMID_ROOT) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case var sccService = _serviceProvider.GetService<SourceControlProvider>(); string directory, fileName, userFile; ErrorHandler.ThrowOnFailure(_vsSolution.GetSolutionInfo(out directory, out fileName, out userFile)); var rgpszFullPaths = new[] {fileName}; var rgsiGlyphs = new VsStateIcon[1]; sccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, new uint[1]); // Set the solution's glyph directly in the hierarchy ((IVsHierarchy)_vsSolution).SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } }
public int SccGlyphChanged(int cAffectedNodes, uint[] rgitemidAffectedNodes, VsStateIcon[] rgsiNewGlyphs, uint[] rgdwNewSccStatus) { if (cAffectedNodes == 0 || rgitemidAffectedNodes == null || rgsiNewGlyphs == null || rgdwNewSccStatus == null){ // This means VS wants us to call StateIconIndex property change listeners for all nodes in the hierarchy. this.OnPropertyChanged(this, (int) __VSHPROPID.VSHPROPID_StateIconIndex, 0); // Walk the project node's descendants depth-first HierarchyNode n = this.firstChild; for (;;){ if (n is HierarchyItemNode) n.OnPropertyChanged(n, (int) __VSHPROPID.VSHPROPID_StateIconIndex, 0); if (n.firstChild != null) n = n.firstChild; else{ for (;;){ if (n == this) goto done; if (n.nextSibling != null){ n = n.nextSibling; break; } n = n.parentNode; } } } done:; }else{ for (int i = 0; i < cAffectedNodes; i++){ HierarchyNode node = this.NodeFromItemId(rgitemidAffectedNodes[i]); node.OnPropertyChanged(node, (int) __VSHPROPID.VSHPROPID_StateIconIndex, 0); } } return (int)HResult.S_OK; }
/// <summary> /// This function determines which glyph to display, given a combination of status flags. /// </summary> /// <param name="dwSccStatus">The dw SCC status.</param> /// <param name="psiGlyph">The psi glyph.</param> /// <returns></returns> public int GetSccGlyphFromStatus(uint dwSccStatus, VsStateIcon[] psiGlyph) { // This method is called when some user (e.g. like classview) wants to combine icons // (Unfortunately classview uses a hardcoded mapping) psiGlyph[0] = VsStateIcon.STATEICON_BLANK; return VSConstants.S_OK; }
public int SccGlyphChanged(int cAffectedNodes, uint[] rgitemidAffectedNodes, VsStateIcon[] rgsiNewGlyphs, uint[] rgdwNewSccStatus) { return VSConstants.S_OK; }
public int GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { rgsiGlyphs[0] = (VsStateIcon)GetGlyphFromPath(rgpszFullPaths[0]); rgdwSccStatus[0] = (uint)SccStatus.SccStatusControlled; return VSConstants.S_OK; }
/// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> public void RefreshNodesGlyphs(IList <VSITEMSELECTION> selectedNodes) { foreach (VSITEMSELECTION vsItemSel in selectedNodes) { var sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case var rgpszFullPaths = new string[1]; rgpszFullPaths[0] = GetSolutionFileName(); var rgsiGlyphs = new VsStateIcon[1]; var rgdwSccStatus = new uint[1]; _sccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy var solHier = (IVsHierarchy)GetService(typeof(SVsSolution)); solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyphs() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); } } else { // DAB 12/2/11: For some reason the example code commented out below stopped working for subordinate files, // such as a windows form and its designer file. The form would be affected but not the designer // Refresh all the glyphs in the project; the project will call back GetSccGlyphs() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); // DAB 12/2/11: The original code, from the sample: //// It may be easier/faster to simply refresh all the nodes in the project, //// and let the project call back on GetSccGlyphs, but just for the sake of the demo, //// let's refresh ourselves only one node at a time //IList<string> sccFiles = GetNodeFiles(sccProject2, vsItemSel.itemid); //// We'll use for the node glyph just the Master file's status (ignoring special files of the node) //if (sccFiles.Count > 0) //{ // var rgpszFullPaths = new string[1]; // rgpszFullPaths[0] = sccFiles[0]; // var rgsiGlyphs = new VsStateIcon[1]; // var rgdwSccStatus = new uint[1]; // _sccService.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // var rguiAffectedNodes = new uint[1]; // rguiAffectedNodes[0] = vsItemSel.itemid; // sccProject2.SccGlyphChanged(1, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); //} } } }
/// <summary> /// Refreshes the glyphs of the specified hierarchy nodes /// </summary> public void RefreshGlyphs(IList<VSITEMSELECTION> selectedNodes) { foreach (VSITEMSELECTION vsItemSel in selectedNodes) { var sccProject2 = vsItemSel.pHier as IVsSccProject2; if (vsItemSel.itemid == VSConstants.VSITEMID_ROOT) { if (sccProject2 == null) { // Note: The solution's hierarchy does not implement IVsSccProject2, IVsSccProject interfaces // It may be a pain to treat the solution as special case everywhere; a possible workaround is // to implement a solution-wrapper class, that will implement IVsSccProject2, IVsSccProject and // IVsHierarhcy interfaces, and that could be used in provider's code wherever a solution is needed. // This approach could unify the treatment of solution and projects in the provider's code. // Until then, solution is treated as special case var rgpszFullPaths = new[] { GetSolutionFileName() }; var rgsiGlyphs = new VsStateIcon[1]; var rgdwSccStatus = new uint[1]; this.GetSccGlyph(1, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); // Set the solution's glyph directly in the hierarchy var solHier = (IVsHierarchy)this.Package.GetService<SVsSolution>(); solHier.SetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]); } else { // Refresh all the glyphs in the project; the project will call back GetSccGlyphs() // with the files for each node that will need new glyph sccProject2.SccGlyphChanged(0, null, null, null); } } else { // It may be easier/faster to simply refresh all the nodes in the project, // and let the project call back on GetSccGlyphs, but just for the sake of the demo, // let's refresh ourselves only one node at a time //IList<string> sccFiles = GetNodeFiles(sccProject2, vsItemSel.itemid); // We'll use for the node glyph just the Master file's status (ignoring special files of the node) //if (sccFiles.Count > 0) UpdateNode(vsItemSel); } } }
public async Task QuickRefreshNodesGlyphs(IVsSccProject2 project, List<string> files) { try { if (files.Count > 0) { string[] rgpszFullPaths = new string[files.Count]; for (int i = 0; i < files.Count; i++) rgpszFullPaths[i] = files[i]; VsStateIcon[] rgsiGlyphs = new VsStateIcon[files.Count]; uint[] rgdwSccStatus = new uint[files.Count]; GetSccGlyph(files.Count, rgpszFullPaths, rgsiGlyphs, rgdwSccStatus); uint[] rguiAffectedNodes = new uint[files.Count]; //TODO We could/Should cache this mapping !!!! await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IList<uint> subnodes = await SolutionExtensions.GetProjectItems((IVsHierarchy)project, VSConstants.VSITEMID_ROOT); var dict = new Dictionary<string, uint>(); var proj = project as IVsProject2; foreach (var id in subnodes) { string docname; var res = proj.GetMkDocument(id, out docname); if (res == VSConstants.S_OK && !string.IsNullOrEmpty(docname)) dict[docname] = id; } for (int i = 0; i < files.Count; ++i) { uint id; if (dict.TryGetValue(files[i], out id)) { rguiAffectedNodes[i] = id; } } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); project.SccGlyphChanged(files.Count, rguiAffectedNodes, rgsiGlyphs, rgdwSccStatus); } } catch (Exception ex) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsActivityLog log = _sccProvider.GetService(typeof(SVsActivityLog)) as IVsActivityLog; if (log == null) return; int hr = log.LogEntry((UInt32)__ACTIVITYLOG_ENTRYTYPE.ALE_ERROR, ex.StackTrace, string.Format(CultureInfo.CurrentCulture, "Called for: {0}", this.ToString())); } }
[CLSCompliant(false)] // Implements 2 interfaces public int GetSccGlyph(int cFiles, string[] rgpszFullPaths, VsStateIcon[] rgsiGlyphs, uint[] rgdwSccStatus) { try { if (rgpszFullPaths == null || rgsiGlyphs == null) { return(VSErr.E_POINTER); // Documented as impossible } if (!IsActive) { for (int i = 0; i < cFiles; i++) { if (rgsiGlyphs != null) { rgsiGlyphs[i] = VsStateIcon.STATEICON_NOSTATEICON; } if (rgdwSccStatus != null) { rgdwSccStatus[i] = (uint)SccStatus.SCC_STATUS_NOTCONTROLLED; } } return(VSErr.S_OK); } for (int i = 0; i < cFiles; i++) { string file = rgpszFullPaths[i]; if (!IsSafeSccPath(file)) { rgsiGlyphs[i] = VsStateIcon.STATEICON_BLANK; if (rgdwSccStatus != null) { rgdwSccStatus[i] = (uint)SccStatus.SCC_STATUS_NOTCONTROLLED; } continue; } AnkhGlyph glyph = GetPathGlyph(file); if (rgsiGlyphs != null) { VsStateIcon icon = (VsStateIcon)glyph; if (icon == VsStateIcon.STATEICON_BLANK || icon == VsStateIcon.STATEICON_NOSTATEICON) { rgsiGlyphs[i] = icon; } else { rgsiGlyphs[i] = (VsStateIcon)((int)icon + _glyphOffset); } } if (rgdwSccStatus != null) { // This will make VS use the right texts on refactor, replace, etc. rgdwSccStatus[i] = GlyphToStatus(glyph); } } return(VSErr.S_OK); } catch (Exception e) { return(VSErr.GetHRForException(e)); } }