PageRenderTime 25ms CodeModel.GetById 14ms app.highlight 7ms RepoModel.GetById 1ms app.codeStats 1ms

/IronPython_Main/Tools/IronStudio/IronStudio/VisualStudio/Project/Automation/OAProjectItems.cs

#
C# | 230 lines | 136 code | 30 blank | 64 comment | 35 complexity | 1e156963074dc8c996cfed4ad91eb6a9 MD5 | raw file
  1/* ****************************************************************************
  2 *
  3 * Copyright (c) Microsoft Corporation. 
  4 *
  5 * This source code is subject to terms and conditions of the Apache License, Version 2.0. A 
  6 * copy of the license can be found in the License.html file at the root of this distribution. If 
  7 * you cannot locate the Apache License, Version 2.0, please send an email to 
  8 * ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound 
  9 * by the terms of the Apache License, Version 2.0.
 10 *
 11 * You must not remove this notice, or any other, from this software.
 12 *
 13 * ***************************************************************************/
 14
 15using System;
 16using System.Diagnostics;
 17using System.Diagnostics.CodeAnalysis;
 18using System.Globalization;
 19using System.IO;
 20using System.Runtime.InteropServices;
 21using EnvDTE;
 22using Microsoft.VisualStudio;
 23using Microsoft.VisualStudio.Shell.Interop;
 24
 25namespace Microsoft.VisualStudio.Project.Automation
 26{
 27	/// <summary>
 28	/// Contains ProjectItem objects
 29	/// </summary>
 30	[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
 31	[ComVisible(true), CLSCompliant(false)]
 32	public class OAProjectItems : OANavigableProjectItems
 33	{
 34		#region ctor
 35		public OAProjectItems(OAProject project, HierarchyNode nodeWithItems)
 36			: base(project, nodeWithItems)
 37		{
 38		}
 39		#endregion
 40
 41		#region EnvDTE.ProjectItems
 42		/// <summary>
 43		/// Creates a new project item from an existing item template file and adds it to the project. 
 44		/// </summary>
 45		/// <param name="fileName">The full path and file name of the template project file.</param>
 46		/// <param name="name">The file name to use for the new project item.</param>
 47		/// <returns>A ProjectItem object. </returns>
 48		public override EnvDTE.ProjectItem AddFromTemplate(string fileName, string name)
 49		{
 50
 51			if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
 52			{
 53				throw new InvalidOperationException();
 54			}
 55
 56			ProjectNode proj = this.Project.Project;
 57			EnvDTE.ProjectItem itemAdded = null;
 58
 59			using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
 60			{
 61				// Determine the operation based on the extension of the filename.
 62				// We should run the wizard only if the extension is vstemplate
 63				// otherwise it's a clone operation
 64				VSADDITEMOPERATION op;
 65
 66				if(Utilities.IsTemplateFile(fileName))
 67				{
 68					op = VSADDITEMOPERATION.VSADDITEMOP_RUNWIZARD;
 69				}
 70				else
 71				{
 72					op = VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE;
 73				}
 74
 75				VSADDRESULT[] result = new VSADDRESULT[1];
 76
 77				// It is not a very good idea to throw since the AddItem might return Cancel or Abort.
 78				// The problem is that up in the call stack the wizard code does not check whether it has received a ProjectItem or not and will crash.
 79				// The other problem is that we cannot get add wizard dialog back if a cancel or abort was returned because we throw and that code will never be executed. Typical catch 22.
 80				ErrorHandler.ThrowOnFailure(proj.AddItem(this.NodeWithItems.ID, op, name, 0, new string[1] { fileName }, IntPtr.Zero, result));
 81
 82				string fileDirectory = proj.GetBaseDirectoryForAddingFiles(this.NodeWithItems);
 83				string templateFilePath = System.IO.Path.Combine(fileDirectory, name);
 84				itemAdded = this.EvaluateAddResult(result[0], templateFilePath);
 85			}
 86
 87			return itemAdded;
 88		}
 89
 90		/// <summary>
 91		/// Adds a folder to the collection of ProjectItems with the given name.
 92		/// 
 93		/// The kind must be null, empty string, or the string value of vsProjectItemKindPhysicalFolder.
 94		/// Virtual folders are not supported by this implementation.
 95		/// </summary>
 96		/// <param name="name">The name of the new folder to add</param>
 97		/// <param name="kind">A string representing a Guid of the folder kind.</param>
 98		/// <returns>A ProjectItem representing the newly added folder.</returns>
 99		public override ProjectItem AddFolder(string name, string kind)
100		{
101			if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
102			{
103				throw new InvalidOperationException();
104			}
105			//Verify name is not null or empty
106			Utilities.ValidateFileName(this.Project.Project.Site, name);
107
108			//Verify that kind is null, empty, or a physical folder
109			if(!(string.IsNullOrEmpty(kind) || kind.Equals(EnvDTE.Constants.vsProjectItemKindPhysicalFolder)))
110			{
111				throw new ArgumentException("Parameter specification for AddFolder was not meet", "kind");
112			}
113
114			for(HierarchyNode child = this.NodeWithItems.FirstChild; child != null; child = child.NextSibling)
115			{
116				if(child.Caption.Equals(name, StringComparison.OrdinalIgnoreCase))
117				{
118					throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, "Folder already exists with the name '{0}'", name));
119				}
120			}
121
122			ProjectNode proj = this.Project.Project;
123
124			HierarchyNode newFolder = null;
125			using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
126			{
127
128				//In the case that we are adding a folder to a folder, we need to build up
129				//the path to the project node.
130				name = Path.Combine(this.NodeWithItems.VirtualNodeName, name);
131
132				newFolder = proj.CreateFolderNodes(name);
133			}
134
135			return newFolder.GetAutomationObject() as ProjectItem;
136		}
137
138		/// <summary>
139		/// Copies a source file and adds it to the project.
140		/// </summary>
141		/// <param name="filePath">The path and file name of the project item to be added.</param>
142		/// <returns>A ProjectItem object. </returns>
143		public override EnvDTE.ProjectItem AddFromFileCopy(string filePath)
144		{
145			return this.AddItem(filePath, VSADDITEMOPERATION.VSADDITEMOP_CLONEFILE);
146		}
147
148		/// <summary>
149		/// Adds a project item from a file that is installed in a project directory structure. 
150		/// </summary>
151		/// <param name="fileName">The file name of the item to add as a project item. </param>
152		/// <returns>A ProjectItem object. </returns>
153		public override EnvDTE.ProjectItem AddFromFile(string fileName)
154		{
155			// TODO: VSADDITEMOP_LINKTOFILE
156			return this.AddItem(fileName, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE);
157		}
158
159		#endregion
160
161		#region helper methods
162		/// <summary>
163		/// Adds an item to the project.
164		/// </summary>
165		/// <param name="path">The full path of the item to add.</param>
166		/// <param name="op">The <paramref name="VSADDITEMOPERATION"/> to use when adding the item.</param>
167		/// <returns>A ProjectItem object. </returns>
168		protected virtual EnvDTE.ProjectItem AddItem(string path, VSADDITEMOPERATION op)
169		{
170			if(this.Project == null || this.Project.Project == null || this.Project.Project.Site == null || this.Project.Project.IsClosed)
171			{
172				throw new InvalidOperationException();
173			}
174
175			ProjectNode proj = this.Project.Project;
176
177			EnvDTE.ProjectItem itemAdded = null;
178			using(AutomationScope scope = new AutomationScope(this.Project.Project.Site))
179			{
180				VSADDRESULT[] result = new VSADDRESULT[1];
181				ErrorHandler.ThrowOnFailure(proj.AddItem(this.NodeWithItems.ID, op, path, 0, new string[1] { path }, IntPtr.Zero, result));
182
183				string fileName = System.IO.Path.GetFileName(path);
184				string fileDirectory = proj.GetBaseDirectoryForAddingFiles(this.NodeWithItems);
185				string filePathInProject = System.IO.Path.Combine(fileDirectory, fileName);
186
187				itemAdded = this.EvaluateAddResult(result[0], filePathInProject);
188			}
189
190			return itemAdded;
191		}
192
193		/// <summary>
194		/// Evaluates the result of an add operation.
195		/// </summary>
196		/// <param name="result">The <paramref name="VSADDRESULT"/> returned by the Add methods</param>
197		/// <param name="path">The full path of the item added.</param>
198		/// <returns>A ProjectItem object.</returns>
199		[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
200		protected virtual EnvDTE.ProjectItem EvaluateAddResult(VSADDRESULT result, string path)
201		{
202			if(result == VSADDRESULT.ADDRESULT_Success)
203			{
204				HierarchyNode nodeAdded = this.NodeWithItems.FindChild(path);
205				Debug.Assert(nodeAdded != null, "We should have been able to find the new element in the hierarchy");
206				if(nodeAdded != null)
207				{
208					EnvDTE.ProjectItem item = null;
209					if(nodeAdded is FileNode)
210					{
211						item = new OAFileItem(this.Project, nodeAdded as FileNode);
212					}
213					else if(nodeAdded is NestedProjectNode)
214					{
215						item = new OANestedProjectItem(this.Project, nodeAdded as NestedProjectNode);
216					}
217					else
218					{
219						item = new OAProjectItem<HierarchyNode>(this.Project, nodeAdded);
220					}
221
222					this.Items.Add(item);
223					return item;
224				}
225			}
226			return null;
227		}
228		#endregion
229	}
230}