Browse Source

Separate NewFileDialog from the FileTemplate implementation (use only the abstract base class).

pull/32/merge
Daniel Grunwald 12 years ago
parent
commit
83d6c5efd7
  1. 3
      samples/PortSD4AddInToSD5/PortSD4AddInToSD5.addin
  2. 5
      src/Main/Base/Project/Src/Gui/Components/LocalizedPropertyGrid/LocalizedProperty.cs
  3. 246
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs
  4. 8
      src/Main/Base/Project/Src/Gui/Dialogs/NewProjectDialog.cs
  5. 242
      src/Main/Base/Project/Src/Internal/Templates/File/FileTemplate.cs
  6. 4
      src/Main/Base/Project/Src/Internal/Templates/File/ScriptRunner.cs
  7. 6
      src/Main/Base/Project/Templates/FileTemplate.cs
  8. 6
      src/Main/SharpDevelop/Project/ProjectService.cs
  9. 26
      src/Main/SharpDevelop/Services/UIService.cs
  10. 6
      src/Main/SharpDevelop/SharpDevelop.csproj
  11. 7
      src/Main/SharpDevelop/Templates/TemplateFileDoozer.cs
  12. 2
      src/Main/SharpDevelop/Templates/TemplateService.cs
  13. 144
      src/Main/SharpDevelop/app.config
  14. 2
      src/Tools/UpdateAssemblyInfo/Main.cs

3
samples/PortSD4AddInToSD5/PortSD4AddInToSD5.addin

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
<AddIn name = "PortSD4AddInToSD5"
author = "Daniel Grunwald"
description = "Issue Providers that help porting SD4 AddIns to SD5">
description = "Issue Providers that help porting SD4 AddIns to SD5"
addInManagerHidden="preinstalled">
<Runtime>
<Import assembly = "PortSD4AddInToSD5.dll"/>

5
src/Main/Base/Project/Src/Gui/Components/LocalizedPropertyGrid/LocalizedProperty.cs

@ -6,10 +6,11 @@ using System.Collections.Generic; @@ -6,10 +6,11 @@ using System.Collections.Generic;
using System.ComponentModel;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.SharpDevelop.Gui
namespace ICSharpCode.SharpDevelop.Templates
{
public class LocalizedProperty : PropertyDescriptor
internal class LocalizedProperty : PropertyDescriptor
{
string category;
string description;

246
src/Main/Base/Project/Src/Gui/Dialogs/NewFileDialog.cs

@ -29,20 +29,14 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -29,20 +29,14 @@ namespace ICSharpCode.SharpDevelop.Gui
{
ArrayList alltemplates = new ArrayList();
ArrayList categories = new ArrayList();
Hashtable icons = new Hashtable();
Dictionary<IImage, int> icons = new Dictionary<IImage, int>();
bool allowUntitledFiles;
IProject project;
DirectoryName basePath;
List<KeyValuePair<string, FileDescriptionTemplate>> createdFiles = new List<KeyValuePair<string, FileDescriptionTemplate>>();
internal FileTemplateOptions options;
internal FileTemplateResult result;
public List<KeyValuePair<string, FileDescriptionTemplate>> CreatedFiles {
get {
return createdFiles;
}
}
public NewFileDialog(IProject project, DirectoryName basePath)
public NewFileDialog(IProject project, DirectoryName basePath, IEnumerable<FileTemplate> fileTemplates)
{
StandardHeader.SetHeaders();
this.project = project;
@ -50,7 +44,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -50,7 +44,7 @@ namespace ICSharpCode.SharpDevelop.Gui
this.allowUntitledFiles = basePath == null;
try {
InitializeComponents();
InitializeTemplates();
InitializeTemplates(fileTemplates);
InitializeView();
if (allowUntitledFiles)
@ -76,20 +70,18 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -76,20 +70,18 @@ namespace ICSharpCode.SharpDevelop.Gui
imglist.Images.Add(IconService.GetBitmap("Icons.32x32.EmptyFileIcon"));
int i = 0;
Hashtable tmp = new Hashtable(icons);
foreach (DictionaryEntry entry in icons) {
Bitmap bitmap = IconService.GetBitmap(entry.Key.ToString());
foreach (var image in icons.Keys.ToArray()) {
Bitmap bitmap = image.Bitmap;
if (bitmap != null) {
smalllist.Images.Add(bitmap);
imglist.Images.Add(bitmap);
tmp[entry.Key] = ++i;
icons[image] = ++i;
} else {
LoggingService.Warn("NewFileDialog: can't load bitmap " + entry.Key.ToString() + " using default");
LoggingService.Warn("NewFileDialog: can't load bitmap " + image.ToString() + " using default");
}
}
icons = tmp;
foreach (TemplateItem item in alltemplates) {
if (item.Template.Icon == null) {
item.ImageIndex = 0;
@ -155,24 +147,18 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -155,24 +147,18 @@ namespace ICSharpCode.SharpDevelop.Gui
return newsubcategory;
}
void InitializeTemplates()
void InitializeTemplates(IEnumerable<FileTemplate> fileTemplates)
{
foreach (FileTemplate template in FileTemplate.FileTemplates) {
foreach (FileTemplate template in fileTemplates) {
TemplateItem titem = new TemplateItem(template);
if (titem.Template.Icon != null) {
icons[titem.Template.Icon] = 0; // "create template icon"
}
if (template.NewFileDialogVisible == true) {
if (template.IsVisible(project)) {
Category cat = GetCategory(StringParser.Parse(titem.Template.Category), StringParser.Parse(titem.Template.Subcategory));
cat.Templates.Add(titem);
cat.Selected = true;
if (!cat.HasSelectedTemplate && titem.Template.FileDescriptionTemplates.Count == 1) {
if (((FileDescriptionTemplate)titem.Template.FileDescriptionTemplates[0]).Name.StartsWith("Empty")) {
titem.Selected = true;
cat.HasSelectedTemplate = true;
}
}
}
alltemplates.Add(titem);
}
@ -209,67 +195,15 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -209,67 +195,15 @@ namespace ICSharpCode.SharpDevelop.Gui
const int GridWidth = 256;
const int GridMargin = 8;
PropertyGrid propertyGrid = new PropertyGrid();
LocalizedTypeDescriptor localizedTypeDescriptor = null;
bool AllPropertiesHaveAValue {
get {
foreach (TemplateProperty property in SelectedTemplate.Properties) {
string val = StringParserPropertyContainer.LocalizedProperty["Properties." + property.Name];
if (val == null || val.Length == 0) {
return false;
}
}
return true;
}
}
object localizedTypeDescriptor = null;
void ShowPropertyGrid()
{
if (localizedTypeDescriptor == null) {
localizedTypeDescriptor = new LocalizedTypeDescriptor();
}
if (!Controls.Contains(propertyGrid)) {
this.SuspendLayout();
propertyGrid.Location = new Point(Width - GridMargin, GridMargin);
propertyGrid.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom;
localizedTypeDescriptor.Properties.Clear();
foreach (TemplateProperty property in SelectedTemplate.Properties) {
LocalizedProperty localizedProperty;
if (property.Type.StartsWith("Types:")) {
localizedProperty = new LocalizedProperty(property.Name, "System.Enum", property.Category, property.Description);
TemplateType type = null;
foreach (TemplateType templateType in SelectedTemplate.CustomTypes) {
if (templateType.Name == property.Type.Substring("Types:".Length)) {
type = templateType;
break;
}
}
if (type == null) {
throw new Exception("type : " + property.Type + " not found.");
}
localizedProperty.TypeConverterObject = new CustomTypeConverter(type);
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = property.DefaultValue;
localizedProperty.DefaultValue = property.DefaultValue; // localizedProperty.TypeConverterObject.ConvertFrom();
} else {
localizedProperty = new LocalizedProperty(property.Name, property.Type, property.Category, property.Description);
if (property.Type == "System.Boolean") {
localizedProperty.TypeConverterObject = new BooleanTypeConverter();
string defVal = property.DefaultValue == null ? null : property.DefaultValue.ToString();
if (defVal == null || defVal.Length == 0) {
defVal = "True";
}
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = defVal;
localizedProperty.DefaultValue = Boolean.Parse(defVal);
} else {
string defVal = property.DefaultValue == null ? String.Empty : property.DefaultValue.ToString();
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = defVal;
localizedProperty.DefaultValue = defVal;
}
}
localizedProperty.LocalizedName = property.LocalizedName;
localizedTypeDescriptor.Properties.Add(localizedProperty);
}
propertyGrid.ToolbarVisible = false;
propertyGrid.SelectedObject = localizedTypeDescriptor;
propertyGrid.Size = new Size(GridWidth, Height - GridMargin * 4);
@ -300,32 +234,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -300,32 +234,7 @@ namespace ICSharpCode.SharpDevelop.Gui
}
string GenerateCurrentFileName()
{
if (SelectedTemplate.DefaultName.IndexOf("${Number}") >= 0) {
try {
int curNumber = 1;
while (true) {
string fileName = StringParser.Parse(SelectedTemplate.DefaultName, new StringTagPair("Number", curNumber.ToString()));
if (allowUntitledFiles) {
bool found = false;
foreach (string openFile in FileService.GetOpenFiles()) {
if (Path.GetFileName(openFile) == fileName) {
found = true;
break;
}
}
if (found == false)
return fileName;
} else if (!File.Exists(Path.Combine(basePath, fileName))) {
return fileName;
}
++curNumber;
}
} catch (Exception e) {
MessageService.ShowException(e);
}
}
return StringParser.Parse(SelectedTemplate.DefaultName);
return SelectedTemplate.SuggestFileName(basePath);
}
bool isNameModified = false;
@ -336,7 +245,8 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -336,7 +245,8 @@ namespace ICSharpCode.SharpDevelop.Gui
if (templateListView.SelectedItems.Count == 1) {
ControlDictionary["descriptionLabel"].Text = StringParser.Parse(SelectedTemplate.Description);
ControlDictionary["openButton"].Enabled = true;
if (SelectedTemplate.HasProperties) {
localizedTypeDescriptor = SelectedTemplate.CreateCustomizationObject();
if (localizedTypeDescriptor != null) {
ShowPropertyGrid();
}
if (!this.allowUntitledFiles && !isNameModified) {
@ -362,59 +272,6 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -362,59 +272,6 @@ namespace ICSharpCode.SharpDevelop.Gui
templateListView.View = ((RadioButton)ControlDictionary["smallIconsRadioButton"]).Checked ? View.List : View.LargeIcon;
}
public bool IsFilenameAvailable(string fileName)
{
if (Path.IsPathRooted(fileName)) {
return !File.Exists(fileName);
}
return true;
}
public void SaveFile(FileDescriptionTemplate newfile, string content, string binaryFileName)
{
string unresolvedFileName = StringParser.Parse(newfile.Name);
// Parse twice so that tags used in included standard header are parsed
string parsedContent = StringParser.Parse(StringParser.Parse(content));
if (parsedContent != null) {
if (SD.EditorControlService.GlobalOptions.IndentationString != "\t") {
parsedContent = parsedContent.Replace("\t", SD.EditorControlService.GlobalOptions.IndentationString);
}
}
// when newFile.Name is "${Path}/${FileName}", there might be a useless '/' in front of the file name
// if the file is created when no project is opened. So we remove single '/' or '\', but not double
// '\\' (project is saved on network share).
if (unresolvedFileName.StartsWith("/") && !unresolvedFileName.StartsWith("//")
|| unresolvedFileName.StartsWith("\\") && !unresolvedFileName.StartsWith("\\\\"))
{
unresolvedFileName = unresolvedFileName.Substring(1);
}
if (newfile.IsDependentFile && Path.IsPathRooted(unresolvedFileName)) {
Directory.CreateDirectory(Path.GetDirectoryName(unresolvedFileName));
if (!String.IsNullOrEmpty(binaryFileName))
File.Copy(binaryFileName, unresolvedFileName);
else
File.WriteAllText(unresolvedFileName, parsedContent, SD.FileService.DefaultFileEncoding);
} else {
if (!String.IsNullOrEmpty(binaryFileName)) {
LoggingService.Warn("binary file was skipped");
return;
}
IViewContent viewContent = FileService.NewFile(Path.GetFileName(unresolvedFileName), parsedContent);
if (viewContent == null) {
return;
}
if (Path.IsPathRooted(unresolvedFileName)) {
Directory.CreateDirectory(Path.GetDirectoryName(unresolvedFileName));
viewContent.PrimaryFile.SaveToDisk(FileName.Create(unresolvedFileName));
}
}
createdFiles.Add(new KeyValuePair<string, FileDescriptionTemplate>(unresolvedFileName, newfile));
}
internal static string GenerateValidClassOrNamespaceName(string className, bool allowDot)
{
if (className == null)
@ -444,18 +301,13 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -444,18 +301,13 @@ namespace ICSharpCode.SharpDevelop.Gui
PropertyService.Set("Dialogs.NewFileDialog.CategoryViewState", TreeViewHelper.GetViewStateString(categoryTreeView));
PropertyService.Set("Dialogs.NewFileDialog.LastSelectedCategory", TreeViewHelper.GetPath(categoryTreeView.SelectedNode));
}
createdFiles.Clear();
if (templateListView.SelectedItems.Count == 1) {
if (!AllPropertiesHaveAValue) {
MessageService.ShowMessage("${res:Dialog.NewFile.FillOutFirstMessage}", "${res:Dialog.NewFile.FillOutFirstCaption}");
return;
}
TemplateItem item = (TemplateItem)templateListView.SelectedItems[0];
PropertyService.Set("Dialogs.NewFileDialog.LastSelectedTemplate", item.Template.Name);
string fileName;
StringParserPropertyContainer.FileCreation["StandardNamespace"] = "DefaultNamespace";
string standardNamespace = "DefaultNamespace";
if (allowUntitledFiles) {
fileName = GenerateCurrentFileName();
} else {
@ -468,12 +320,12 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -468,12 +320,12 @@ namespace ICSharpCode.SharpDevelop.Gui
return;
}
if (Path.GetExtension(fileName).Length == 0) {
fileName += Path.GetExtension(item.Template.DefaultName);
fileName += Path.GetExtension(item.Template.SuggestFileName(null));
}
fileName = Path.Combine(basePath, fileName);
fileName = FileUtility.NormalizePath(fileName);
if (project != null) {
StringParserPropertyContainer.FileCreation["StandardNamespace"] = CustomToolsService.GetDefaultNamespace(project, fileName);
standardNamespace = CustomToolsService.GetDefaultNamespace(project, fileName);
}
}
@ -481,62 +333,14 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -481,62 +333,14 @@ namespace ICSharpCode.SharpDevelop.Gui
options.ClassName = GenerateValidClassOrNamespaceName(Path.GetFileNameWithoutExtension(fileName), false);
options.FileName = FileName.Create(fileName);
options.IsUntitled = allowUntitledFiles;
options.Namespace = StringParserPropertyContainer.FileCreation["StandardNamespace"];
StringParserPropertyContainer.FileCreation["FullName"] = fileName;
StringParserPropertyContainer.FileCreation["FileName"] = Path.GetFileName(fileName);
StringParserPropertyContainer.FileCreation["FileNameWithoutExtension"] = Path.GetFileNameWithoutExtension(fileName);
StringParserPropertyContainer.FileCreation["Extension"] = Path.GetExtension(fileName);
StringParserPropertyContainer.FileCreation["Path"] = Path.GetDirectoryName(fileName);
StringParserPropertyContainer.FileCreation["ClassName"] = options.ClassName;
// when adding a file to a project (but not when creating a standalone file while a project is open):
if (project != null && !this.allowUntitledFiles) {
options.Project = project;
// add required assembly references to the project
bool changes = false;
foreach (ReferenceProjectItem reference in item.Template.RequiredAssemblyReferences) {
IEnumerable<ProjectItem> refs = project.GetItemsOfType(ItemType.Reference);
if (!refs.Any(projItem => string.Equals(projItem.Include, reference.Include, StringComparison.OrdinalIgnoreCase))) {
ReferenceProjectItem projItem = (ReferenceProjectItem)reference.CloneFor(project);
ProjectService.AddProjectItem(project, projItem);
changes = true;
}
}
if (changes) {
project.Save();
}
}
foreach (FileDescriptionTemplate newfile in item.Template.FileDescriptionTemplates) {
if (!IsFilenameAvailable(StringParser.Parse(newfile.Name))) {
MessageService.ShowError(string.Format("Filename {0} is in use.\nChoose another one", StringParser.Parse(newfile.Name))); // TODO : translate
return;
}
}
ScriptRunner scriptRunner = new ScriptRunner();
foreach (FileDescriptionTemplate newFile in item.Template.FileDescriptionTemplates) {
FileOperationResult result = FileUtility.ObservedSave(
() => {
if (!String.IsNullOrEmpty(newFile.BinaryFileName)) {
SaveFile(newFile, null, newFile.BinaryFileName);
} else {
SaveFile(newFile, scriptRunner.CompileScript(item.Template, newFile), null);
}
}, FileName.Create(StringParser.Parse(newFile.Name))
);
if (result != FileOperationResult.OK)
return;
}
options.Namespace = standardNamespace;
options.CustomizationObject = localizedTypeDescriptor;
options.Project = project;
result = SelectedTemplate.Create(options);
DialogResult = DialogResult.OK;
// raise FileCreated event for the new files.
foreach (KeyValuePair<string, FileDescriptionTemplate> entry in createdFiles) {
FileService.FireFileCreated(entry.Key, false);
}
item.Template.RunActions(options);
if (result != null)
SelectedTemplate.RunActions(result);
}
}

8
src/Main/Base/Project/Src/Gui/Dialogs/NewProjectDialog.cs

@ -34,12 +34,12 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -34,12 +34,12 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
set { locationTextBox.Text = value; }
}
public NewProjectDialog(bool createNewSolution)
public NewProjectDialog(bool createNewSolution, IEnumerable<ProjectTemplate> projectTemplates)
{
this.createNewSolution = createNewSolution;
MyInitializeComponents();
InitializeTemplates();
InitializeTemplates(projectTemplates);
InitializeView();
locationTextBox.Text = PropertyService.Get("ICSharpCode.SharpDevelop.Gui.Dialogs.NewProjectDialog.DefaultPath", Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "SharpDevelop Projects"));
@ -135,9 +135,9 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs @@ -135,9 +135,9 @@ namespace ICSharpCode.SharpDevelop.Project.Dialogs
return newsubcategory;
}
protected virtual void InitializeTemplates()
protected virtual void InitializeTemplates(IEnumerable<ProjectTemplate> projectTemplates)
{
foreach (ProjectTemplate template in SD.Templates.ProjectTemplates) {
foreach (ProjectTemplate template in projectTemplates) {
if (!template.IsVisible(SolutionFolder != null ? SolutionFolder.ParentSolution : null)) {
// Do not show solution template when added a new project to existing solution
continue;

242
src/Main/Base/Project/Src/Internal/Templates/File/FileTemplate.cs

@ -9,8 +9,8 @@ using System.Linq; @@ -9,8 +9,8 @@ using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Input;
using System.Xml;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Templates;
@ -101,15 +101,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -101,15 +101,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
/// <summary>
/// This class defines and holds the new file templates.
/// </summary>
internal class FileTemplate : IComparable
internal class FileTemplateImpl : FileTemplate
{
public static List<FileTemplate> FileTemplates = new List<FileTemplate>();
string author = null;
string name = null;
string category = null;
string languagename = null;
string icon = null;
IImage icon = null;
string description = null;
string wizardpath = null;
string defaultName = null;
@ -123,33 +121,24 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -123,33 +121,24 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
List<ReferenceProjectItem> requiredAssemblyReferences = new List<ReferenceProjectItem>();
XmlElement fileoptions = null;
Action<FileTemplateOptions> actions;
int IComparable.CompareTo(object other)
{
FileTemplate pt = other as FileTemplate;
if (pt == null) return -1;
int res = category.CompareTo(pt.category);
if (res != 0) return res;
return name.CompareTo(pt.name);
}
Action<FileTemplateResult> actions;
public string Author {
get {
return author;
}
}
public string Name {
public override string Name {
get {
return name;
}
}
public string Category {
public override string Category {
get {
return category;
}
}
public string Subcategory {
public override string Subcategory {
get {
return subcategory;
}
@ -159,12 +148,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -159,12 +148,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
return languagename;
}
}
public string Icon {
public override IImage Icon {
get {
return icon;
}
}
public string Description {
public override string Description {
get {
return description;
}
@ -219,13 +208,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -219,13 +208,13 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public FileTemplate(XmlDocument doc, IReadOnlyFileSystem fileSystem)
public FileTemplateImpl(XmlDocument doc, IReadOnlyFileSystem fileSystem)
{
author = doc.DocumentElement.GetAttribute("author");
XmlElement config = doc.DocumentElement["Config"];
name = config.GetAttribute("name");
icon = config.GetAttribute("icon");
icon = SD.ResourceService.GetImage(config.GetAttribute("icon"));
category = config.GetAttribute("category");
defaultName = config.GetAttribute("defaultname");
languagename = config.GetAttribute("language");
@ -279,7 +268,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -279,7 +268,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
if (doc.DocumentElement["Actions"] != null) {
foreach (XmlElement el in doc.DocumentElement["Actions"]) {
Action<FileTemplateOptions> action = ReadAction(el);
Action<FileTemplateResult> action = ReadAction(el);
if (action != null)
actions += action;
}
@ -297,7 +286,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -297,7 +286,7 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
static Action<FileTemplateOptions> ReadAction(XmlElement el)
static Action<FileTemplateResult> ReadAction(XmlElement el)
{
switch (el.Name) {
case "RunCommand":
@ -319,10 +308,211 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -319,10 +308,211 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
}
}
public void RunActions(FileTemplateOptions options)
public override void RunActions(FileTemplateResult result)
{
if (actions != null)
actions(options);
actions(result);
}
public override string SuggestFileName(DirectoryName basePath)
{
if (defaultName.IndexOf("${Number}") >= 0) {
try {
int curNumber = 1;
while (true) {
string fileName = StringParser.Parse(defaultName, new StringTagPair("Number", curNumber.ToString()));
if (basePath == null) {
bool found = false;
foreach (string openFile in FileService.GetOpenFiles()) {
if (Path.GetFileName(openFile) == fileName) {
found = true;
break;
}
}
if (found == false)
return fileName;
} else if (!File.Exists(Path.Combine(basePath, fileName))) {
return fileName;
}
++curNumber;
}
} catch (Exception e) {
MessageService.ShowException(e);
}
}
return StringParser.Parse(defaultName);
}
public override object CreateCustomizationObject()
{
if (!HasProperties)
return null;
LocalizedTypeDescriptor localizedTypeDescriptor = new LocalizedTypeDescriptor();
foreach (TemplateProperty property in Properties) {
LocalizedProperty localizedProperty;
if (property.Type.StartsWith("Types:")) {
localizedProperty = new LocalizedProperty(property.Name, "System.Enum", property.Category, property.Description);
TemplateType type = null;
foreach (TemplateType templateType in CustomTypes) {
if (templateType.Name == property.Type.Substring("Types:".Length)) {
type = templateType;
break;
}
}
if (type == null) {
throw new Exception("type : " + property.Type + " not found.");
}
localizedProperty.TypeConverterObject = new CustomTypeConverter(type);
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = property.DefaultValue;
localizedProperty.DefaultValue = property.DefaultValue; // localizedProperty.TypeConverterObject.ConvertFrom();
} else {
localizedProperty = new LocalizedProperty(property.Name, property.Type, property.Category, property.Description);
if (property.Type == "System.Boolean") {
localizedProperty.TypeConverterObject = new BooleanTypeConverter();
string defVal = property.DefaultValue == null ? null : property.DefaultValue.ToString();
if (defVal == null || defVal.Length == 0) {
defVal = "True";
}
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = defVal;
localizedProperty.DefaultValue = Boolean.Parse(defVal);
} else {
string defVal = property.DefaultValue == null ? String.Empty : property.DefaultValue.ToString();
StringParserPropertyContainer.LocalizedProperty["Properties." + localizedProperty.Name] = defVal;
localizedProperty.DefaultValue = defVal;
}
}
localizedProperty.LocalizedName = property.LocalizedName;
localizedTypeDescriptor.Properties.Add(localizedProperty);
}
return localizedTypeDescriptor;
}
public override FileTemplateResult Create(FileTemplateOptions options)
{
FileTemplateResult result = new FileTemplateResult(options);
StringParserPropertyContainer.FileCreation["StandardNamespace"] = options.Namespace;
StringParserPropertyContainer.FileCreation["FullName"] = options.FileName;
StringParserPropertyContainer.FileCreation["FileName"] = Path.GetFileName(options.FileName);
StringParserPropertyContainer.FileCreation["FileNameWithoutExtension"] = Path.GetFileNameWithoutExtension(options.FileName);
StringParserPropertyContainer.FileCreation["Extension"] = Path.GetExtension(options.FileName);
StringParserPropertyContainer.FileCreation["Path"] = Path.GetDirectoryName(options.FileName);
StringParserPropertyContainer.FileCreation["ClassName"] = options.ClassName;
// when adding a file to a project (but not when creating a standalone file while a project is open):
var project = options.Project;
if (project != null && !options.IsUntitled) {
// add required assembly references to the project
foreach (ReferenceProjectItem reference in RequiredAssemblyReferences) {
IEnumerable<ProjectItem> refs = project.GetItemsOfType(ItemType.Reference);
if (!refs.Any(projItem => string.Equals(projItem.Include, reference.Include, StringComparison.OrdinalIgnoreCase))) {
ReferenceProjectItem projItem = (ReferenceProjectItem)reference.CloneFor(project);
ProjectService.AddProjectItem(project, projItem);
ProjectBrowserPad.RefreshViewAsync();
}
}
}
foreach (FileDescriptionTemplate newfile in FileDescriptionTemplates) {
if (!IsFilenameAvailable(StringParser.Parse(newfile.Name))) {
MessageService.ShowError(string.Format("Filename {0} is in use.\nChoose another one", StringParser.Parse(newfile.Name))); // TODO : translate
return null;
}
}
var createdFiles = new List<KeyValuePair<string, FileDescriptionTemplate>>();
ScriptRunner scriptRunner = new ScriptRunner();
foreach (FileDescriptionTemplate newFile in FileDescriptionTemplates) {
FileOperationResult opresult = FileUtility.ObservedSave(
() => {
string resultFile;
if (!String.IsNullOrEmpty(newFile.BinaryFileName)) {
resultFile = SaveFile(newFile, null, newFile.BinaryFileName);
} else {
resultFile = SaveFile(newFile, scriptRunner.CompileScript(this, newFile), null);
}
if (resultFile != null) {
result.NewFiles.Add(FileName.Create(resultFile));
createdFiles.Add(new KeyValuePair<string, FileDescriptionTemplate>(resultFile, newFile));
}
}, FileName.Create(StringParser.Parse(newFile.Name))
);
if (opresult != FileOperationResult.OK)
return null;
}
if (project != null) {
foreach (KeyValuePair<string, FileDescriptionTemplate> createdFile in createdFiles) {
FileName fileName = FileName.Create(createdFile.Key);
ItemType type = project.GetDefaultItemType(fileName);
FileProjectItem newItem = new FileProjectItem(project, type);
newItem.FileName = fileName;
createdFile.Value.SetProjectItemProperties(newItem);
project.Items.Add(newItem);
}
project.Save();
}
// raise FileCreated event for the new files.
foreach (var fileName in result.NewFiles) {
FileService.FireFileCreated(fileName, false);
}
return result;
}
bool IsFilenameAvailable(string fileName)
{
if (Path.IsPathRooted(fileName)) {
return !File.Exists(fileName);
}
return true;
}
string SaveFile(FileDescriptionTemplate newfile, string content, string binaryFileName)
{
string unresolvedFileName = StringParser.Parse(newfile.Name);
// Parse twice so that tags used in included standard header are parsed
string parsedContent = StringParser.Parse(StringParser.Parse(content));
if (parsedContent != null) {
if (SD.EditorControlService.GlobalOptions.IndentationString != "\t") {
parsedContent = parsedContent.Replace("\t", SD.EditorControlService.GlobalOptions.IndentationString);
}
}
// when newFile.Name is "${Path}/${FileName}", there might be a useless '/' in front of the file name
// if the file is created when no project is opened. So we remove single '/' or '\', but not double
// '\\' (project is saved on network share).
if (unresolvedFileName.StartsWith("/") && !unresolvedFileName.StartsWith("//")
|| unresolvedFileName.StartsWith("\\") && !unresolvedFileName.StartsWith("\\\\"))
{
unresolvedFileName = unresolvedFileName.Substring(1);
}
if (newfile.IsDependentFile && Path.IsPathRooted(unresolvedFileName)) {
Directory.CreateDirectory(Path.GetDirectoryName(unresolvedFileName));
if (!String.IsNullOrEmpty(binaryFileName))
File.Copy(binaryFileName, unresolvedFileName);
else
File.WriteAllText(unresolvedFileName, parsedContent, SD.FileService.DefaultFileEncoding);
} else {
if (!String.IsNullOrEmpty(binaryFileName)) {
LoggingService.Warn("binary file was skipped");
return null;
}
IViewContent viewContent = FileService.NewFile(Path.GetFileName(unresolvedFileName), parsedContent);
if (viewContent == null) {
return null;
}
if (Path.IsPathRooted(unresolvedFileName)) {
Directory.CreateDirectory(Path.GetDirectoryName(unresolvedFileName));
viewContent.PrimaryFile.SaveToDisk(FileName.Create(unresolvedFileName));
}
}
return unresolvedFileName;
}
}
}

4
src/Main/Base/Project/Src/Internal/Templates/File/ScriptRunner.cs

@ -15,12 +15,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates @@ -15,12 +15,12 @@ namespace ICSharpCode.SharpDevelop.Internal.Templates
{
internal class ScriptRunner
{
FileTemplate item;
FileTemplateImpl item;
FileDescriptionTemplate file;
readonly static Regex scriptRegex = new Regex("<%.*?%>");
public string CompileScript(FileTemplate item, FileDescriptionTemplate file)
public string CompileScript(FileTemplateImpl item, FileDescriptionTemplate file)
{
if (file.Content == null)
throw new ArgumentException("file must have textual content");

6
src/Main/Base/Project/Templates/FileTemplate.cs

@ -7,7 +7,7 @@ using ICSharpCode.SharpDevelop.Project; @@ -7,7 +7,7 @@ using ICSharpCode.SharpDevelop.Project;
namespace ICSharpCode.SharpDevelop.Templates
{
public abstract class FileTemplate
public abstract class FileTemplate : TemplateBase
{
/// <summary>
/// Gets whether this template is available for the specified project.
@ -39,5 +39,9 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -39,5 +39,9 @@ namespace ICSharpCode.SharpDevelop.Templates
/// Instanciates the template, writes the new files to disk, and adds them to the project.
/// </summary>
public abstract FileTemplateResult Create(FileTemplateOptions options);
public virtual void RunActions(FileTemplateResult result)
{
}
}
}

6
src/Main/SharpDevelop/Project/ProjectService.cs

@ -315,7 +315,7 @@ namespace ICSharpCode.SharpDevelop.Project @@ -315,7 +315,7 @@ namespace ICSharpCode.SharpDevelop.Project
throw new ArgumentNullException("fileName");
if (progress == null)
throw new ArgumentNullException("progress");
if (!Path.IsPathRooted(fileName))
if (fileName.IsRelative)
throw new ArgumentException("Path must be rooted!");
Solution solution = new Solution(fileName, new ProjectChangeWatcher(fileName), SD.FileService);
bool ok = false;
@ -333,6 +333,10 @@ namespace ICSharpCode.SharpDevelop.Project @@ -333,6 +333,10 @@ namespace ICSharpCode.SharpDevelop.Project
public ISolution CreateEmptySolutionFile(FileName fileName)
{
if (fileName == null)
throw new ArgumentNullException("fileName");
if (fileName.IsRelative)
throw new ArgumentException("Path must be rooted!");
Solution solution = new Solution(fileName, new ProjectChangeWatcher(fileName), SD.FileService);
solution.LoadPreferences();
return solution;

26
src/Main/SharpDevelop/Services/UIService.cs

@ -30,31 +30,19 @@ namespace ICSharpCode.SharpDevelop @@ -30,31 +30,19 @@ namespace ICSharpCode.SharpDevelop
}
}
public FileTemplateResult ShowNewFileDialog(IProject project, DirectoryName directory, IEnumerable<ICSharpCode.SharpDevelop.Templates.FileTemplate> templates)
public FileTemplateResult ShowNewFileDialog(IProject project, DirectoryName directory, IEnumerable<FileTemplate> templates)
{
using (NewFileDialog nfd = new NewFileDialog(project, directory)) {
if (nfd.ShowDialog(SD.WinForms.MainWin32Window) != DialogResult.OK)
using (NewFileDialog nfd = new NewFileDialog(project, directory, templates ?? SD.Templates.FileTemplates)) {
if (nfd.ShowDialog(SD.WinForms.MainWin32Window) == DialogResult.OK)
return nfd.result;
else
return null;
if (project != null) {
foreach (KeyValuePair<string, FileDescriptionTemplate> createdFile in nfd.CreatedFiles) {
FileName fileName = FileName.Create(createdFile.Key);
ItemType type = project.GetDefaultItemType(fileName);
FileProjectItem newItem = new FileProjectItem(project, type);
newItem.FileName = fileName;
createdFile.Value.SetProjectItemProperties(newItem);
project.Items.Add(newItem);
}
project.Save();
}
var result = new FileTemplateResult(nfd.options);
result.NewFiles.AddRange(nfd.CreatedFiles.Select(p => FileName.Create(p.Key)));
return result;
}
}
public ProjectTemplateResult ShowNewProjectDialog(ISolutionFolder solutionFolder, IEnumerable<ICSharpCode.SharpDevelop.Templates.ProjectTemplate> templates)
public ProjectTemplateResult ShowNewProjectDialog(ISolutionFolder solutionFolder, IEnumerable<ProjectTemplate> templates)
{
using (NewProjectDialog npdlg = new NewProjectDialog(createNewSolution: solutionFolder == null)) {
using (NewProjectDialog npdlg = new NewProjectDialog(createNewSolution: solutionFolder == null, projectTemplates: templates ?? SD.Templates.ProjectTemplates)) {
npdlg.SolutionFolder = solutionFolder;
if (solutionFolder != null) {
npdlg.InitialProjectLocationDirectory = AddNewProjectToSolution.GetInitialDirectorySuggestion(solutionFolder);

6
src/Main/SharpDevelop/SharpDevelop.csproj

@ -212,9 +212,9 @@ @@ -212,9 +212,9 @@
<LogicalName>Resources.SplashScreen.jpg</LogicalName>
</EmbeddedResource>
<Compile Include="Configuration\AssemblyInfo.cs" />
<None Include="SharpDevelop.exe.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Content Include="app.config">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Content>
<Compile Include="..\GlobalAssemblyInfo.cs">
<Link>Configuration\GlobalAssemblyInfo.cs</Link>
<DependentUpon>GlobalAssemblyInfo.template</DependentUpon>

7
src/Main/SharpDevelop/Templates/TemplateFileDoozer.cs

@ -47,9 +47,12 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -47,9 +47,12 @@ namespace ICSharpCode.SharpDevelop.Templates
{
var fileSystem = GetFileSystem(args);
var templates = new List<TemplateBase>();
foreach (var fileName in fileSystem.GetFiles(DirectoryName.Create("."), "*.xpt", SearchOption.AllDirectories)) {
var xpt = fileSystem.GetFiles(DirectoryName.Create("."), "*.xpt", SearchOption.AllDirectories);
var xft = fileSystem.GetFiles(DirectoryName.Create("."), "*.xft", SearchOption.AllDirectories);
foreach (var fileName in xpt.Concat(xft)) {
using (var stream = fileSystem.OpenRead(fileName)) {
templates.Add(SD.Templates.LoadTemplate(stream, fileSystem));
var relFileSystem = new ReadOnlyChrootFileSystem(fileSystem, fileName.GetParentDirectory());
templates.Add(SD.Templates.LoadTemplate(stream, relFileSystem));
}
}
if (templates.Count == 1)

2
src/Main/SharpDevelop/Templates/TemplateService.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Templates @@ -56,7 +56,7 @@ namespace ICSharpCode.SharpDevelop.Templates
XmlDocument doc = new XmlDocument();
doc.Load(stream);
if (doc.DocumentElement["Files"] != null)
throw new NotImplementedException();
return new FileTemplateImpl(doc, fileSystem);
else if (doc.DocumentElement["Project"] != null || doc.DocumentElement["Solution"] != null)
return new ProjectTemplateImpl(doc, fileSystem);
else

144
src/Main/SharpDevelop/app.config

@ -0,0 +1,144 @@ @@ -0,0 +1,144 @@
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>
<!--
WARNING!
This file is automatically generated and will be overwritten every time SharpDevelop is compiled.
Change the template file "app.template.config" instead!
-->
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<runtime>
<!-- This option allows running SharpDevelop from network drives -->
<loadFromRemoteSources enabled="true" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<!-- The redirects for SharpDevelop allow using old AddIns in newer SharpDevelop versions -->
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.Core" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.Core.WinForms" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.Core.Presentation" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.SharpDevelop" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.SharpDevelop.Widgets" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.TreeView" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="FormsDesigner" publicKeyToken="f829da5c02be14ee" culture="neutral"/>
<bindingRedirect oldVersion="5.0.0.0-5.0.0.2379" newVersion="5.0.0.2379"/>
</dependentAssembly>
<!-- redirect MSBuild.Framework requests to make old task assemblies work with MSBuild 4.0 -->
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="4.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.CompactFramework.Build.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-99.9.9.9" newVersion="10.0.0.0"/>
</dependentAssembly>
<probing privatePath="Tools\NUnit"/>
</assemblyBinding>
</runtime>
<appSettings>
<!-- Use this configuration setting to store settings in a directory relative to the location
of SharpDevelop.exe instead of the user's profile directory. -->
<!-- <add key="settingsPath" value="..\Settings" /> -->
<!-- Use this setting to specify a different path for the code completion cache.
The cache contains information about referenced assemblies to speed up loading
the information on future SharpDevelop starts. -->
<!-- <add key="domPersistencePath" value="..\DomCache" /> -->
<!-- Use this setting to disable the code completion cache. Code completion will still be
available, but take longer to load and use more RAM. -->
<!-- <add key="domPersistencePath" value="none" /> -->
</appSettings>
<log4net>
<!-- Writes to the console. The console is only visible in debug builds of SharpDevelop. -->
<appender name="ColoredConsoleAppender" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="FATAL" />
<foreColor value="Red, HighIntensity" />
</mapping>
<mapping>
<level value="ERROR" />
<foreColor value="Red" />
</mapping>
<mapping>
<level value="WARN" />
<foreColor value="Yellow" />
</mapping>
<mapping>
<level value="INFO" />
<foreColor value="White" />
</mapping>
<mapping>
<level value="DEBUG" />
<foreColor value="Green" />
</mapping>
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level- %message%newline" />
</layout>
</appender>
<!-- Writes to OutputDebugString - use a tool like Sysinternals DebugView to view the log -->
<appender name="DebugAppender" type="log4net.Appender.OutputDebugStringAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="[%thread] %-5level- %message%newline" />
</layout>
</appender>
<!-- Allows writing to a log file -->
<appender name="FileAppender" type="log4net.Appender.FileAppender">
<file value="SharpDevelopLog.txt" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level- %message%newline" />
</layout>
</appender>
<!--- Keeps the last few log entries and appends them to bug reports when an exception occurs -->
<appender name="Recorder" type="ICSharpCode.SharpDevelop.Logging.LogMessageRecorder, SharpDevelop">
<bufferSize value="25" />
</appender>
<root>
<level value="DEBUG" />
<!-- Here you can configure which log appenders should be used -->
<appender-ref ref="ColoredConsoleAppender" />
<appender-ref ref="Recorder" />
</root>
</log4net>
</configuration>

2
src/Tools/UpdateAssemblyInfo/Main.cs

@ -30,7 +30,7 @@ namespace UpdateAssemblyInfo @@ -30,7 +30,7 @@ namespace UpdateAssemblyInfo
},
new TemplateFile {
Input = "src/Main/SharpDevelop/app.template.config",
Output = "src/Main/SharpDevelop/SharpDevelop.exe.config"
Output = "src/Main/SharpDevelop/app.config"
},
new TemplateFile {
Input = "src/Setup/SharpDevelop.Setup.wixproj.user.template",

Loading…
Cancel
Save