/* **************************************************************************** * * Copyright (c) Microsoft Corporation. * * This source code is subject to terms and conditions of the Apache License, Version 2.0. A * copy of the license can be found in the License.html file at the root of this distribution. If * you cannot locate the Apache License, Version 2.0, please send an email to * vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound * by the terms of the Apache License, Version 2.0. * * You must not remove this notice, or any other, from this software. * * ***************************************************************************/ using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Security.Permissions; using System.Text; using Microsoft.VisualStudio; using Microsoft.VisualStudio.Shell.Interop; using OleConstants = Microsoft.VisualStudio.OLE.Interop.Constants; using VsCommands2K = Microsoft.VisualStudio.VSConstants.VSStd2KCmdID; namespace Microsoft.VisualStudio.Project { public abstract class ReferenceNode : HierarchyNode #if DEV11_OR_LATER ,IVsReference, IEquatable #endif { public delegate void CannotAddReferenceErrorMessage(); public event EventHandler ReferenceRefreshed; #region ctors /// /// constructor for the ReferenceNode /// protected ReferenceNode(ProjectNode root, ProjectElement element) : base(root, element) { this.ExcludeNodeFromScc = true; } /// /// constructor for the ReferenceNode /// public ReferenceNode(ProjectNode root) : base(root) { this.ExcludeNodeFromScc = true; } #endregion #region overridden properties public override int MenuCommandId { get { return VsMenus.IDM_VS_CTXT_REFERENCE; } } public override Guid ItemTypeGuid { get { return Guid.Empty; } } public override string Url { get { return String.Empty; } } public override string Caption { get { return String.Empty; } } #endregion #region overridden methods protected override NodeProperties CreatePropertiesObject() { return new ReferenceNodeProperties(this); } /// /// Get an instance of the automation object for ReferenceNode /// /// An instance of Automation.OAReferenceItem type if succeeded public override object GetAutomationObject() { if (this.ProjectMgr == null || this.ProjectMgr.IsClosed) { return null; } return new Automation.OAReferenceItem(this.ProjectMgr.GetAutomationObject() as Automation.OAProject, this); } /// /// Disable inline editing of Caption of a ReferendeNode /// /// null public override string GetEditLabel() { return null; } public override object GetIconHandle(bool open) { int offset = (this.CanShowDefaultIcon() ? (int)ProjectNode.ImageName.Reference : (int)ProjectNode.ImageName.DanglingReference); return this.ProjectMgr.ImageHandler.GetIconHandle(offset); } /// /// This method is called by the interface method GetMkDocument to specify the item moniker. /// /// The moniker for this item public override string GetMkDocument() { return this.Url; } /// /// Not supported. /// public override int ExcludeFromProject() { return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED; } public override void Remove(bool removeFromStorage) { ReferenceContainerNode parent = Parent as ReferenceContainerNode; base.Remove(removeFromStorage); if (parent != null) { parent.FireChildRemoved(this); } } /// /// References node cannot be dragged. /// /// A stringbuilder. public override string PrepareSelectedNodesForClipBoard() { return null; } public override int QueryStatusOnNode(Guid cmdGroup, uint cmd, IntPtr pCmdText, ref QueryStatusResult result) { if (cmdGroup == VsMenus.guidStandardCommandSet2K) { if ((VsCommands2K)cmd == VsCommands2K.QUICKOBJECTSEARCH) { result |= QueryStatusResult.SUPPORTED | QueryStatusResult.ENABLED; return VSConstants.S_OK; } } else { return (int)OleConstants.OLECMDERR_E_UNKNOWNGROUP; } return base.QueryStatusOnNode(cmdGroup, cmd, pCmdText, ref result); } public override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut) { if (cmdGroup == VsMenus.guidStandardCommandSet2K) { if ((VsCommands2K)cmd == VsCommands2K.QUICKOBJECTSEARCH) { return this.ShowObjectBrowser(); } } return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut); } #endregion #region methods /// /// Links a reference node to the project and hierarchy. /// public virtual void AddReference() { ReferenceContainerNode referencesFolder = this.ProjectMgr.GetReferenceContainer() as ReferenceContainerNode; Debug.Assert(referencesFolder != null, "Could not find the References node"); CannotAddReferenceErrorMessage referenceErrorMessageHandler = null; if (!this.CanAddReference(out referenceErrorMessageHandler)) { if (referenceErrorMessageHandler != null) { referenceErrorMessageHandler.DynamicInvoke(new object[] { }); } return; } // Link the node to the project file. this.BindReferenceData(); // At this point force the item to be refreshed this.ItemNode.RefreshProperties(); referencesFolder.AddChild(this); return; } /// /// Refreshes a reference by re-resolving it and redrawing the icon. /// public virtual void RefreshReference(bool fileChanged = false) { this.ResolveReference(); ProjectMgr.ReDrawNode(this, UIHierarchyElement.Icon); OnReferenceRefreshed(EventArgs.Empty); } protected virtual void OnReferenceRefreshed(EventArgs e) { if (this.ReferenceRefreshed != null) ReferenceRefreshed(this, e); } /// /// Resolves references. /// protected virtual void ResolveReference() { } /// /// Validates that a reference can be added. /// /// A CannotAddReferenceErrorMessage delegate to show the error message. /// true if the reference can be added. protected virtual bool CanAddReference(out CannotAddReferenceErrorMessage errorHandler) { // When this method is called this refererence has not yet been added to the hierarchy, only instantiated. errorHandler = null; if (this.IsAlreadyAdded()) { return false; } return true; } /// /// Checks if a reference is already added. The method parses all references and compares the Url. /// /// true if the assembly has already been added. protected virtual bool IsAlreadyAdded() { ReferenceContainerNode referencesFolder = this.ProjectMgr.GetReferenceContainer() as ReferenceContainerNode; Debug.Assert(referencesFolder != null, "Could not find the References node"); for (HierarchyNode n = referencesFolder.FirstChild; n != null; n = n.NextSibling) { ReferenceNode refererenceNode = n as ReferenceNode; if (null != refererenceNode) { // We check if the Url of the assemblies is the same. if (CommonUtils.IsSamePath(refererenceNode.Url, this.Url)) { return true; } } } return false; } /// /// Shows the Object Browser /// /// protected virtual int ShowObjectBrowser() { if (String.IsNullOrEmpty(this.Url) || !File.Exists(this.Url)) { return (int)OleConstants.OLECMDERR_E_NOTSUPPORTED; } // Request unmanaged code permission in order to be able to creaet the unmanaged memory representing the guid. new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand(); Guid guid = VSConstants.guidCOMPLUSLibrary; IntPtr ptr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(guid.ToByteArray().Length); System.Runtime.InteropServices.Marshal.StructureToPtr(guid, ptr, false); int returnValue = VSConstants.S_OK; try { VSOBJECTINFO[] objInfo = new VSOBJECTINFO[1]; objInfo[0].pguidLib = ptr; objInfo[0].pszLibName = this.Url; IVsObjBrowser objBrowser = this.ProjectMgr.Site.GetService(typeof(SVsObjBrowser)) as IVsObjBrowser; ErrorHandler.ThrowOnFailure(objBrowser.NavigateTo(objInfo, 0)); } catch (COMException e) { Trace.WriteLine("Exception" + e.ErrorCode); returnValue = e.ErrorCode; } finally { if (ptr != IntPtr.Zero) { System.Runtime.InteropServices.Marshal.FreeCoTaskMem(ptr); } } return returnValue; } public override bool CanDeleteItem(__VSDELETEITEMOPERATION deleteOperation) { if (deleteOperation == __VSDELETEITEMOPERATION.DELITEMOP_RemoveFromProject) { return true; } return false; } protected abstract void BindReferenceData(); #endregion #if DEV11_OR_LATER public virtual bool AlreadyReferenced { get { return this.ProjectMgr.GetReferenceContainer().ContainsReference(this); } set { this.ProjectMgr.GetReferenceContainer().AddReference(this); } } public virtual string FullPath { get { return Url; } set { throw new NotSupportedException(); } } public virtual string Name { get { return Caption; } set { throw new NotSupportedException(); } } public abstract string ReferenceType { get; } #region IEquatable members public abstract bool Equals(IVsReference other); #endregion #endif } }