none
How to update glyph for specific project item in Solution Explorer?

    Question

  • Hi guys,

    I'm trying to find a way how to update project items glyphs in Solution Explorer. I've created VSIX package, implemented IVsSccProvider class (with million other interfaces) which of course contains method GetSccGlyph. This method calls automatically when solution opens and all glyphs are set correctly first time. Later, when I need to update specific glyphs (let's say statuses of some files can be changed) - I'm trying to use the following code

    var rgsiGlyphs = new VsStateIcon[1];

    var rgdwSccStatus = new uint[1];

    GetSccGlyph(1, new[] { itemFilePath }, rgsiGlyphs, rgdwSccStatus);

    hierarchy.SetProperty(itemId, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]);

    where  itemId is specific project item id in solutiom. This code perfectly works for solution item but not for project / class items. Hacks like force refreshing all project child items with method

    sccProject2.SccGlyphChanged(0, null, null, null);

    does not help as well. I read in a couple of articles that all statuses are actually cached and they need to be force reload but again I can't find any useful information regarding this point. How it should be done? And why there are no references in MSDN in article about SccGlyphChanged?

    Have anyone faced with the same problem? 

    Thanks.

    Monday, June 25, 2012 12:32 PM

Answers

  • IVsHierarchy.SetProperty(VSHPROPID_StateIconIndex) is the wrong function to call for projects. The correct thing to call to let the project know the status glyphs are changed is to obtain IVsSccProject2 interface from the project's hierarchy and to call IVsSccProject2.SccGlyphChanged, and pass in the number of nodes that changed status, their new status glyphs index and scci status flags.

    You can also call SccGlyphChanged(0, null, null, null), but depending on what changed that may be completely inefficient, as the project will then refresh the scc status of all nodes in the project. Note that projects may or may not use the rgsiNewGlyphs/rgdwNewSccStatus arguments in the call, and may instead call back on IVsSccManager2.GetSccGlyphs() for the affected noded (they will definitely call that function if you force a refresh of all glyphs)

    That solution node is a special case - the solution does not implement IVsSccProject2, therefore you cannot call SccGlyphChanged. For the solution node you can update the status glyph by calling IVsHierarchy.SetProperty(VSHPROPID_StateIconIndex).

    Once the glyphs are obtained by the projects, it is true that projects will then usually cache the status (to avoid calling GetSccGlyph every time nodes in SolutionExplorer need repaining). This is why notifying projects of status changes with SccGlyphChanged is necessary, that will allow the projects to invalidate their cache and use or re-query the updated values.

    If you're implementing a source control provider I suggest you also look at http://code.msdn.microsoft.com/windowsdesktop/Source-Code-Control-11362626 which demonstrate many of the necessary interaction calls with an scc provider, including SccGlyphsChanged.

    Alin

    Tuesday, June 26, 2012 6:09 PM

All replies

  • Is this your hierarchy or a built in one?  Does SetProperty return S_OK or a failure code?

    Ryan

    Monday, June 25, 2012 3:47 PM
    Moderator
  • Hi Ryan,

    Thank you very much for your response!

    It is a built in hierarchy. So what my code is doing - it is running though the solution hierarchy recursively and calls the method which contains 

    hierarchy.SetProperty(itemId, (int)__VSHPROPID.VSHPROPID_StateIconIndex, rgsiGlyphs[0]);

    I checked that SetProperty returns S_OK only for solution item (as I mentioned previously it applies changed only for solution item glyph as well) and -2147467263 for all other items (and doesn't change glyphs). So what I'm doing wrong? At least I'm interested if my approach SHOULD work? So if you need to update the glyph of the specific solution item (solution/project/class file) - is it correct to use the approach I used? 

    Thanks,

    Andrey

    Tuesday, June 26, 2012 7:11 AM
  • -2147467263 (0x80004001) is E_NOTIMPL, a return of anything other than S_OK means the call you made failed, so that is why nothing changes.  I don't believe most (any?) hierarchies support people mucking with these kinds of properties from the outside, the generally get the state information from the SCC provider afaik. I will point someone that knows about the SCC interaction this way, he may be able to shed some light on how you are supposed to accomplish this.

    Ryan

    Tuesday, June 26, 2012 5:18 PM
    Moderator
  • IVsHierarchy.SetProperty(VSHPROPID_StateIconIndex) is the wrong function to call for projects. The correct thing to call to let the project know the status glyphs are changed is to obtain IVsSccProject2 interface from the project's hierarchy and to call IVsSccProject2.SccGlyphChanged, and pass in the number of nodes that changed status, their new status glyphs index and scci status flags.

    You can also call SccGlyphChanged(0, null, null, null), but depending on what changed that may be completely inefficient, as the project will then refresh the scc status of all nodes in the project. Note that projects may or may not use the rgsiNewGlyphs/rgdwNewSccStatus arguments in the call, and may instead call back on IVsSccManager2.GetSccGlyphs() for the affected noded (they will definitely call that function if you force a refresh of all glyphs)

    That solution node is a special case - the solution does not implement IVsSccProject2, therefore you cannot call SccGlyphChanged. For the solution node you can update the status glyph by calling IVsHierarchy.SetProperty(VSHPROPID_StateIconIndex).

    Once the glyphs are obtained by the projects, it is true that projects will then usually cache the status (to avoid calling GetSccGlyph every time nodes in SolutionExplorer need repaining). This is why notifying projects of status changes with SccGlyphChanged is necessary, that will allow the projects to invalidate their cache and use or re-query the updated values.

    If you're implementing a source control provider I suggest you also look at http://code.msdn.microsoft.com/windowsdesktop/Source-Code-Control-11362626 which demonstrate many of the necessary interaction calls with an scc provider, including SccGlyphsChanged.

    Alin

    Tuesday, June 26, 2012 6:09 PM
  • Thanks a lot Constantin and Ryan for your help and useful information! 
    Wednesday, June 27, 2012 12:03 PM