PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Main/Base/Project/Src/Internal/Templates/Project/ProjectTemplate.cs

http://github.com/icsharpcode/SharpDevelop
C# | 363 lines | 300 code | 49 blank | 14 comment | 58 complexity | 008b7c478f4085c1d26574e439759a39 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CPL-1.0, LGPL-2.1
  1. // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
  2. // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
  3. using System;
  4. using System.Collections;
  5. using System.Collections.ObjectModel;
  6. using System.Collections.Generic;
  7. using System.Diagnostics;
  8. using System.Linq;
  9. using System.ComponentModel;
  10. using System.IO;
  11. using System.Windows.Forms;
  12. using System.Xml;
  13. using ICSharpCode.Core;
  14. using ICSharpCode.SharpDevelop.Gui;
  15. using ICSharpCode.SharpDevelop.Project;
  16. namespace ICSharpCode.SharpDevelop.Internal.Templates
  17. {
  18. /// <summary>
  19. /// This class defines and holds the new project templates.
  20. /// </summary>
  21. public class ProjectTemplate : IComparable
  22. {
  23. static List<ProjectTemplate> projectTemplates;
  24. /// <summary>
  25. /// Gets the list of project templates. Not thread-safe!
  26. /// </summary>
  27. public static ReadOnlyCollection<ProjectTemplate> ProjectTemplates {
  28. get {
  29. WorkbenchSingleton.AssertMainThread();
  30. #if DEBUG
  31. // Always reload project templates if debugging.
  32. // TODO: Make this a configurable option.
  33. UpdateTemplates();
  34. #else
  35. if (projectTemplates == null) {
  36. UpdateTemplates();
  37. }
  38. #endif
  39. return projectTemplates.AsReadOnly();
  40. }
  41. }
  42. string originator;
  43. string created;
  44. string lastmodified;
  45. string name;
  46. string category;
  47. string languagename;
  48. string description;
  49. string icon;
  50. string subcategory;
  51. TargetFramework[] supportedTargetFrameworks;
  52. internal bool HasSupportedTargetFrameworks {
  53. get { return supportedTargetFrameworks != null; }
  54. }
  55. internal bool SupportsTargetFramework(TargetFramework framework)
  56. {
  57. if (supportedTargetFrameworks == null)
  58. return true;
  59. // return true if framework is based on any of the supported target frameworks
  60. return supportedTargetFrameworks.Any(framework.IsBasedOn);
  61. }
  62. int IComparable.CompareTo(object other)
  63. {
  64. ProjectTemplate pt = other as ProjectTemplate;
  65. if (pt == null) return -1;
  66. int res = category.CompareTo(pt.category);
  67. if (res != 0) return res;
  68. return name.CompareTo(pt.name);
  69. }
  70. bool newProjectDialogVisible = true;
  71. List<Action<ProjectCreateInformation>> openActions = new List<Action<ProjectCreateInformation>>();
  72. SolutionDescriptor solutionDescriptor = null;
  73. ProjectDescriptor projectDescriptor = null;
  74. #region Template Properties
  75. public string Originator {
  76. get {
  77. return originator;
  78. }
  79. }
  80. public string Created {
  81. get {
  82. return created;
  83. }
  84. }
  85. public string LastModified {
  86. get {
  87. return lastmodified;
  88. }
  89. }
  90. public string Name {
  91. get {
  92. return name;
  93. }
  94. }
  95. public string Category {
  96. get {
  97. return category;
  98. }
  99. }
  100. public string Subcategory {
  101. get {
  102. return subcategory;
  103. }
  104. }
  105. public string LanguageName {
  106. get {
  107. return languagename;
  108. }
  109. }
  110. public string Description {
  111. get {
  112. return description;
  113. }
  114. }
  115. public string Icon {
  116. get {
  117. return icon;
  118. }
  119. }
  120. public bool NewProjectDialogVisible {
  121. get {
  122. return newProjectDialogVisible;
  123. }
  124. }
  125. [Browsable(false)]
  126. public SolutionDescriptor SolutionDescriptor {
  127. get {
  128. return solutionDescriptor;
  129. }
  130. }
  131. [Browsable(false)]
  132. public ProjectDescriptor ProjectDescriptor {
  133. get {
  134. return projectDescriptor;
  135. }
  136. }
  137. #endregion
  138. protected ProjectTemplate(string fileName)
  139. {
  140. XmlDocument doc = new XmlDocument();
  141. doc.Load(fileName);
  142. LoadFromXml(doc.DocumentElement, fileName);
  143. }
  144. void LoadFromXml(XmlElement templateElement, string xmlFileName)
  145. {
  146. // required for warning messages for unknown elements
  147. templateElement.SetAttribute("fileName", xmlFileName);
  148. originator = templateElement.GetAttribute("originator");
  149. created = templateElement.GetAttribute("created");
  150. lastmodified = templateElement.GetAttribute("lastModified");
  151. string newProjectDialogVisibleAttr = templateElement.GetAttribute("newprojectdialogvisible");
  152. if (string.Equals(newProjectDialogVisibleAttr, "false", StringComparison.OrdinalIgnoreCase))
  153. newProjectDialogVisible = false;
  154. XmlElement config = templateElement["TemplateConfiguration"];
  155. name = config["Name"].InnerText;
  156. category = config["Category"].InnerText;
  157. if (config["LanguageName"] != null) {
  158. languagename = config["LanguageName"].InnerText;
  159. WarnObsoleteNode(config["LanguageName"], "use language attribute on the project node instead");
  160. }
  161. if (config["Subcategory"] != null) {
  162. subcategory = config["Subcategory"].InnerText;
  163. }
  164. if (config["Description"] != null) {
  165. description = config["Description"].InnerText;
  166. }
  167. if (config["Icon"] != null) {
  168. icon = config["Icon"].InnerText;
  169. }
  170. if (config["SupportedTargetFrameworks"] != null) {
  171. supportedTargetFrameworks =
  172. config["SupportedTargetFrameworks"].InnerText.Split(';')
  173. .Select<string,TargetFramework>(TargetFramework.GetByName).ToArray();
  174. }
  175. string hintPath = Path.GetDirectoryName(xmlFileName);
  176. if (templateElement["Solution"] != null) {
  177. solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Solution"], hintPath);
  178. } else if (templateElement["Combine"] != null) {
  179. solutionDescriptor = SolutionDescriptor.CreateSolutionDescriptor(templateElement["Combine"], hintPath);
  180. WarnObsoleteNode(templateElement["Combine"], "Use <Solution> instead!");
  181. }
  182. if (templateElement["Project"] != null) {
  183. projectDescriptor = new ProjectDescriptor(templateElement["Project"], hintPath);
  184. }
  185. if (solutionDescriptor == null && projectDescriptor == null
  186. || solutionDescriptor != null && projectDescriptor != null)
  187. {
  188. throw new TemplateLoadException("Template must contain either Project or Solution node!");
  189. }
  190. // Read Actions;
  191. if (templateElement["Actions"] != null) {
  192. foreach (XmlElement el in templateElement["Actions"]) {
  193. Action<ProjectCreateInformation> action = ReadAction(el);
  194. if (action != null)
  195. openActions.Add(action);
  196. }
  197. }
  198. }
  199. static Action<ProjectCreateInformation> ReadAction(XmlElement el)
  200. {
  201. switch (el.Name) {
  202. case "Open":
  203. if (el.HasAttribute("filename")) {
  204. string fileName = el.GetAttribute("filename");
  205. return projectCreateInformation => {
  206. string parsedFileName = StringParser.Parse(fileName, new StringTagPair("ProjectName", projectCreateInformation.ProjectName));
  207. string path = Path.Combine(projectCreateInformation.ProjectBasePath, parsedFileName);
  208. FileService.OpenFile(path);
  209. };
  210. } else {
  211. WarnAttributeMissing(el, "filename");
  212. return null;
  213. }
  214. case "RunCommand":
  215. if (el.HasAttribute("path")) {
  216. ICommand command = (ICommand)AddInTree.BuildItem(el.GetAttribute("path"), null);
  217. return projectCreateInformation => {
  218. command.Owner = projectCreateInformation;
  219. command.Run();
  220. };
  221. } else {
  222. WarnAttributeMissing(el, "path");
  223. return null;
  224. }
  225. default:
  226. WarnObsoleteNode(el, "Unknown action element is interpreted as <Open>");
  227. goto case "Open";
  228. }
  229. }
  230. internal static void WarnObsoleteNode(XmlElement element, string message)
  231. {
  232. MessageService.ShowWarning("Obsolete node <" + element.Name +
  233. "> used in '" + element.OwnerDocument.DocumentElement.GetAttribute("fileName") +
  234. "':\n" + message);
  235. }
  236. internal static void WarnObsoleteAttribute(XmlElement element, string attribute, string message)
  237. {
  238. MessageService.ShowWarning("Obsolete attribute <" + element.Name +
  239. " " + attribute + "=...>" +
  240. "used in '" + element.OwnerDocument.DocumentElement.GetAttribute("fileName") +
  241. "':\n" + message);
  242. }
  243. internal static void WarnAttributeMissing(XmlElement element, string attribute)
  244. {
  245. MessageService.ShowWarning("Missing attribute <" + element.Name +
  246. " " + attribute + "=...>" +
  247. " in '" + element.OwnerDocument.DocumentElement.GetAttribute("fileName") +
  248. "'");
  249. }
  250. // string startupProject = null;
  251. public string CreateProject(ProjectCreateInformation projectCreateInformation)
  252. {
  253. LoggingService.Info("Creating project from template '" + this.Category + "/" + this.Subcategory + "/" + this.Name + "'");
  254. if (solutionDescriptor != null) {
  255. return solutionDescriptor.CreateSolution(projectCreateInformation, this.languagename);
  256. } else if (projectDescriptor != null) {
  257. bool createNewSolution = projectCreateInformation.Solution == null;
  258. if (createNewSolution) {
  259. string fileName = Path.Combine(projectCreateInformation.SolutionPath, projectCreateInformation.SolutionName + ".sln");
  260. projectCreateInformation.Solution = new Solution(new ProjectChangeWatcher(fileName));
  261. projectCreateInformation.Solution.Name = projectCreateInformation.SolutionName;
  262. projectCreateInformation.Solution.FileName = fileName;
  263. }
  264. IProject project = projectDescriptor.CreateProject(projectCreateInformation, this.languagename);
  265. if (project != null) {
  266. string solutionLocation = projectCreateInformation.Solution.FileName;
  267. if (createNewSolution) {
  268. projectCreateInformation.Solution.AddFolder(project);
  269. projectCreateInformation.Solution.Save();
  270. ProjectService.OnSolutionCreated(new SolutionEventArgs(projectCreateInformation.Solution));
  271. projectCreateInformation.Solution.Dispose();
  272. } else {
  273. project.Dispose();
  274. }
  275. return solutionLocation;
  276. } else {
  277. if (createNewSolution)
  278. projectCreateInformation.Solution.Dispose();
  279. return null;
  280. }
  281. } else {
  282. return null;
  283. }
  284. }
  285. public void RunOpenActions(ProjectCreateInformation projectCreateInformation)
  286. {
  287. foreach (Action<ProjectCreateInformation> action in openActions) {
  288. action(projectCreateInformation);
  289. }
  290. }
  291. public const string TemplatePath = "/SharpDevelop/BackendBindings/Templates";
  292. public static void UpdateTemplates()
  293. {
  294. projectTemplates = new List<ProjectTemplate>();
  295. string dataTemplateDir = Path.Combine(PropertyService.DataDirectory, "templates", "project");
  296. List<string> files = FileUtility.SearchDirectory(dataTemplateDir, "*.xpt");
  297. foreach (string templateDirectory in AddInTree.BuildItems<string>(TemplatePath, null, false)) {
  298. files.AddRange(FileUtility.SearchDirectory(templateDirectory, "*.xpt"));
  299. }
  300. foreach (string fileName in files) {
  301. try {
  302. projectTemplates.Add(new ProjectTemplate(fileName));
  303. } catch (XmlException e) {
  304. MessageService.ShowError(ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n" + e.Message);
  305. } catch (TemplateLoadException e) {
  306. MessageService.ShowError(ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n" + e.ToString());
  307. } catch (Exception e) {
  308. MessageService.ShowException(e, ResourceService.GetString("Internal.Templates.ProjectTemplate.LoadingError") + "\n(" + fileName + ")\n");
  309. }
  310. }
  311. projectTemplates.Sort();
  312. }
  313. }
  314. }