// // // // // $Revision$ // using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Reflection; using System.Diagnostics; using System.Resources; using System.Windows.Forms; using System.Text; using System.Text.RegularExpressions; using System.Xml; using System.IO; using System.CodeDom.Compiler; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Internal.Templates; using ICSharpCode.SharpDevelop.Gui.XmlForms; namespace ICSharpCode.SharpDevelop.Gui { /// /// This class is for creating a new "empty" file /// public class NewFileDialog : BaseSharpDevelopForm { ArrayList alltemplates = new ArrayList(); ArrayList categories = new ArrayList(); Hashtable icons = new Hashtable(); bool allowUntitledFiles; string basePath; List> createdFiles = new List>(); public List> CreatedFiles { get { return createdFiles; } } public NewFileDialog(string basePath) { StandardHeader.SetHeaders(); this.basePath = basePath; this.allowUntitledFiles = basePath == null; try { InitializeComponents(); InitializeTemplates(); InitializeView(); ((TreeView)ControlDictionary["categoryTreeView"]).Select(); } catch (Exception e) { MessageService.ShowError(e); } } void InitializeView() { ImageList smalllist = new ImageList(); ImageList imglist = new ImageList(); smalllist.ColorDepth = ColorDepth.Depth32Bit; imglist.ColorDepth = ColorDepth.Depth32Bit; imglist.ImageSize = new Size(32, 32); smalllist.ImageSize = new Size(16, 16); smalllist.Images.Add(IconService.GetBitmap("Icons.32x32.EmptyFileIcon")); 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()); if (bitmap != null) { smalllist.Images.Add(bitmap); imglist.Images.Add(bitmap); tmp[entry.Key] = ++i; } else { LoggingService.Warn("NewFileDialog: can't load bitmap " + entry.Key.ToString() + " using default"); } } icons = tmp; foreach (TemplateItem item in alltemplates) { if (item.Template.Icon == null) { item.ImageIndex = 0; } else { item.ImageIndex = (int)icons[item.Template.Icon]; } } ((ListView)ControlDictionary["templateListView"]).LargeImageList = imglist; ((ListView)ControlDictionary["templateListView"]).SmallImageList = smalllist; InsertCategories(null, categories); ((TreeView)ControlDictionary["categoryTreeView"]).TreeViewNodeSorter = new TemplateCategoryComparer(); ((TreeView)ControlDictionary["categoryTreeView"]).Sort(); SelectLastSelectedCategoryNode(((TreeView)ControlDictionary["categoryTreeView"]).Nodes, PropertyService.Get("Dialogs.NewFileDialog.LastSelectedCategory", "C#")); } void InsertCategories(TreeNode node, ArrayList catarray) { foreach (Category cat in catarray) { if (node == null) { ((TreeView)ControlDictionary["categoryTreeView"]).Nodes.Add(cat); } else { node.Nodes.Add(cat); } InsertCategories(cat, cat.Categories); } } TreeNode SelectLastSelectedCategoryNode(TreeNodeCollection nodes, string name) { foreach (TreeNode node in nodes) { if (node.Name == name) { ((TreeView)ControlDictionary["categoryTreeView"]).SelectedNode = node; node.ExpandAll(); return node; } TreeNode selectedNode = SelectLastSelectedCategoryNode(node.Nodes, name); if (selectedNode != null) { return selectedNode; } } return null; } Category GetCategory(string categoryname, string subcategoryname) { foreach (Category category in categories) { if (category.Name == categoryname) { if (subcategoryname == null) { return category; } else { return GetSubcategory(category, subcategoryname); } } } Category newcategory = new Category(categoryname, TemplateCategorySortOrderFile.GetFileCategorySortOrder(categoryname)); categories.Add(newcategory); if (subcategoryname != null) { return GetSubcategory(newcategory, subcategoryname); } return newcategory; } Category GetSubcategory(Category parentCategory, string name) { foreach (Category subcategory in parentCategory.Categories) { if (subcategory.Name == name) return subcategory; } Category newsubcategory = new Category(name, TemplateCategorySortOrderFile.GetFileCategorySortOrder(parentCategory.Name, name)); parentCategory.Categories.Add(newsubcategory); return newsubcategory; } void InitializeTemplates() { foreach (FileTemplate template in FileTemplate.FileTemplates) { TemplateItem titem = new TemplateItem(template); if (titem.Template.Icon != null) { icons[titem.Template.Icon] = 0; // "create template icon" } if (template.NewFileDialogVisible == true) { Category cat = GetCategory(StringParser.Parse(titem.Template.Category), StringParser.Parse(titem.Template.Subcategory)); cat.Templates.Add(titem); if (cat.Selected == false && template.WizardPath == null) { 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); } } // tree view event handlers void CategoryChange(object sender, TreeViewEventArgs e) { ((ListView)ControlDictionary["templateListView"]).Items.Clear(); if (((TreeView)ControlDictionary["categoryTreeView"]).SelectedNode != null) { foreach (TemplateItem item in ((Category)((TreeView)ControlDictionary["categoryTreeView"]).SelectedNode).Templates) { ((ListView)ControlDictionary["templateListView"]).Items.Add(item); } } } void OnBeforeExpand(object sender, TreeViewCancelEventArgs e) { e.Node.ImageIndex = 1; } void OnBeforeCollapse(object sender, TreeViewCancelEventArgs e) { e.Node.ImageIndex = 0; } 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 = StringParser.Properties["Properties." + property.Name]; if (val == null || val.Length == 0) { return false; } } return true; } } void ShowPropertyGrid() { if (localizedTypeDescriptor == null) { localizedTypeDescriptor = new LocalizedTypeDescriptor(); } if (!Controls.Contains(propertyGrid)) { this.SuspendLayout(); propertyGrid.Location = new Point(Width - GridMargin, GridMargin); 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); StringParser.Properties["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"; } StringParser.Properties["Properties." + localizedProperty.Name] = defVal; localizedProperty.DefaultValue = Boolean.Parse(defVal); } } localizedProperty.LocalizedName = property.LocalizedName; localizedTypeDescriptor.Properties.Add(localizedProperty); } propertyGrid.ToolbarVisible = false; propertyGrid.SelectedObject = localizedTypeDescriptor; propertyGrid.Size = new Size(GridWidth, Height - GridMargin * 4); Width = Width + GridWidth; Controls.Add(propertyGrid); this.ResumeLayout(false); } } void HidePropertyGrid() { if (Controls.Contains(propertyGrid)) { this.SuspendLayout(); Controls.Remove(propertyGrid); Width = Width - GridWidth; this.ResumeLayout(false); } } FileTemplate SelectedTemplate { get { if (((ListView)ControlDictionary["templateListView"]).SelectedItems.Count == 1) { return ((TemplateItem)((ListView)ControlDictionary["templateListView"]).SelectedItems[0]).Template; } return null; } } string GenerateCurrentFileName() { if (SelectedTemplate.DefaultName.IndexOf("${Number}") >= 0) { try { int curNumber = 1; while (true) { StringParser.Properties["Number"] = curNumber.ToString(); string fileName = StringParser.Parse(SelectedTemplate.DefaultName); if (allowUntitledFiles) { bool found = false; foreach (string openFile in FileService.GetOpenFiles()) { if (Path.GetFileName(openFile) == fileName) { found = true; break; } } if (found == false) break; } else if (!File.Exists(Path.Combine(basePath, fileName))) { break; } ++curNumber; } } catch (Exception e) { MessageService.ShowError(e); } } return StringParser.Parse(SelectedTemplate.DefaultName); } bool isNameModified = false; // list view event handlers void SelectedIndexChange(object sender, EventArgs e) { if (((ListView)ControlDictionary["templateListView"]).SelectedItems.Count == 1) { ControlDictionary["descriptionLabel"].Text = StringParser.Parse(SelectedTemplate.Description); ControlDictionary["openButton"].Enabled = true; if (SelectedTemplate.HasProperties) { ShowPropertyGrid(); } if (!this.allowUntitledFiles && !isNameModified) { ControlDictionary["fileNameTextBox"].Text = GenerateCurrentFileName(); isNameModified = false; } } else { ControlDictionary["descriptionLabel"].Text = String.Empty; ControlDictionary["openButton"].Enabled = false; HidePropertyGrid(); } } void FileNameChanged(object sender, EventArgs e) { isNameModified = true; } // button events void CheckedChange(object sender, EventArgs e) { ((ListView)ControlDictionary["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 parsedFileName = StringParser.Parse(newfile.Name); string parsedContent = StringParser.Parse(content); if (parsedFileName.StartsWith("/") || parsedFileName.StartsWith("\\")) parsedFileName = parsedFileName.Substring(1); if (newfile.IsDependentFile && Path.IsPathRooted(parsedFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(parsedFileName)); File.WriteAllText(parsedFileName, parsedContent, ParserService.DefaultFileEncoding); ParserService.ParseFile(parsedFileName, parsedContent); } else { IWorkbenchWindow window = FileService.NewFile(Path.GetFileName(parsedFileName), StringParser.Parse(newfile.Language), parsedContent); if (window == null) { return; } if (Path.IsPathRooted(parsedFileName)) { Directory.CreateDirectory(Path.GetDirectoryName(parsedFileName)); window.ViewContent.Save(parsedFileName); } } createdFiles.Add(new KeyValuePair(parsedFileName, newfile.CreateMSBuildProperties())); } string GenerateValidClassName(string className) { int idx = 0; while (idx < className.Length && className[idx] != '_' && !Char.IsLetter(className[idx])) { ++idx; } StringBuilder nameBuilder = new StringBuilder(); for (; idx < className.Length; ++idx) { if (Char.IsLetterOrDigit(className[idx]) || className[idx] == '_') { nameBuilder.Append(className[idx]); } if (className[idx] == ' ' || className[idx] == '-' ) { nameBuilder.Append('_'); } } return nameBuilder.ToString(); } void OpenEvent(object sender, EventArgs e) { if (((TreeView)ControlDictionary["categoryTreeView"]).SelectedNode != null) { PropertyService.Set("Dialogs.NewProjectDialog.LargeImages", ((RadioButton)ControlDictionary["largeIconsRadioButton"]).Checked); PropertyService.Set("Dialogs.NewFileDialog.LastSelectedCategory", ((TreeView)ControlDictionary["categoryTreeView"]).SelectedNode.Text); } createdFiles.Clear(); if (((ListView)ControlDictionary["templateListView"]).SelectedItems.Count == 1) { if (!AllPropertiesHaveAValue) { MessageService.ShowMessage("${res:Dialog.NewFile.FillOutFirstMessage}", "${res:Dialog.NewFile.FillOutFirstCaption}"); return; } TemplateItem item = (TemplateItem)((ListView)ControlDictionary["templateListView"]).SelectedItems[0]; string fileName; StringParser.Properties["StandardNamespace"] = "DefaultNamespace"; if (allowUntitledFiles) { fileName = GenerateCurrentFileName(); } else { fileName = ControlDictionary["fileNameTextBox"].Text; if (Path.GetExtension(fileName).Length == 0) { fileName += Path.GetExtension(item.Template.DefaultName); } fileName = Path.Combine(basePath, fileName); fileName = Path.GetFullPath(fileName); IProject project = ProjectService.CurrentProject; if (project != null) { string relPath = FileUtility.GetRelativePath(project.Directory, Path.GetDirectoryName(fileName)); string[] subdirs = relPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); StringBuilder standardNameSpace = new StringBuilder(project.RootNamespace); foreach(string subdir in subdirs) { if (subdir == "." || subdir == ".." || subdir.Length == 0) continue; if (subdir.Equals("src", StringComparison.OrdinalIgnoreCase)) continue; if (subdir.Equals("source", StringComparison.OrdinalIgnoreCase)) continue; standardNameSpace.Append('.'); standardNameSpace.Append(GenerateValidClassName(subdir)); } StringParser.Properties["StandardNamespace"] = standardNameSpace.ToString(); } } StringParser.Properties["FullName"] = fileName; StringParser.Properties["FileName"] = Path.GetFileName(fileName); StringParser.Properties["FileNameWithoutExtension"] = Path.GetFileNameWithoutExtension(fileName); StringParser.Properties["Extension"] = Path.GetExtension(fileName); StringParser.Properties["Path"] = Path.GetDirectoryName(fileName); StringParser.Properties["ClassName"] = GenerateValidClassName(Path.GetFileNameWithoutExtension(fileName)); if (item.Template.WizardPath != null) { Properties customizer = new Properties(); customizer.Set("Template", item.Template); customizer.Set("Creator", this); WizardDialog wizard = new WizardDialog("File Wizard", customizer, item.Template.WizardPath); if (wizard.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm) == DialogResult.OK) { DialogResult = DialogResult.OK; } } else { foreach (FileDescriptionTemplate newfile in item.Template.FileDescriptionTemplates) { if (!IsFilenameAvailable(StringParser.Parse(newfile.Name))) { MessageService.ShowError("Filename " + StringParser.Parse(newfile.Name) + " is in use.\nChoose another one"); return; } } ScriptRunner scriptRunner = new ScriptRunner(); foreach (FileDescriptionTemplate newfile in item.Template.FileDescriptionTemplates) { SaveFile(newfile, scriptRunner.CompileScript(item.Template, newfile)); } DialogResult = DialogResult.OK; } } } /// /// Represents a category /// public class Category : TreeNode, ICategory { ArrayList categories = new ArrayList(); ArrayList templates = new ArrayList(); int sortOrder = TemplateCategorySortOrderFile.UndefinedSortOrder; public bool Selected = false; public bool HasSelectedTemplate = false; public Category(string name, int sortOrder) : base(StringParser.Parse(name)) { this.Name = StringParser.Parse(name); ImageIndex = 1; this.sortOrder = sortOrder; } public Category(string name) : this(name, TemplateCategorySortOrderFile.UndefinedSortOrder) { } public ArrayList Categories { get { return categories; } } public ArrayList Templates { get { return templates; } } public int SortOrder { get { return sortOrder; } set { sortOrder = value; } } } /// /// Represents a new file template /// class TemplateItem : ListViewItem { FileTemplate template; public TemplateItem(FileTemplate template) : base(StringParser.Parse(template.Name)) { this.template = template; ImageIndex = 0; } public FileTemplate Template { get { return template; } } } void InitializeComponents() { if (allowUntitledFiles) { SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.NewFileDialog.xfrm")); } else { SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.NewFileWithNameDialog.xfrm")); ControlDictionary["fileNameTextBox"].TextChanged += new EventHandler(FileNameChanged); } ImageList imglist = new ImageList(); imglist.ColorDepth = ColorDepth.Depth32Bit; imglist.Images.Add(IconService.GetBitmap("Icons.16x16.OpenFolderBitmap")); imglist.Images.Add(IconService.GetBitmap("Icons.16x16.ClosedFolderBitmap")); ((TreeView)ControlDictionary["categoryTreeView"]).ImageList = imglist; ((TreeView)ControlDictionary["categoryTreeView"]).AfterSelect += new TreeViewEventHandler(CategoryChange); ((TreeView)ControlDictionary["categoryTreeView"]).BeforeSelect += new TreeViewCancelEventHandler(OnBeforeExpand); ((TreeView)ControlDictionary["categoryTreeView"]).BeforeExpand += new TreeViewCancelEventHandler(OnBeforeExpand); ((TreeView)ControlDictionary["categoryTreeView"]).BeforeCollapse += new TreeViewCancelEventHandler(OnBeforeCollapse); ((ListView)ControlDictionary["templateListView"]).SelectedIndexChanged += new EventHandler(SelectedIndexChange); ((ListView)ControlDictionary["templateListView"]).DoubleClick += new EventHandler(OpenEvent); ControlDictionary["openButton"].Click += new EventHandler(OpenEvent); ((RadioButton)ControlDictionary["largeIconsRadioButton"]).Checked = PropertyService.Get("Dialogs.NewProjectDialog.LargeImages", true); ((RadioButton)ControlDictionary["largeIconsRadioButton"]).CheckedChanged += new EventHandler(CheckedChange); ((RadioButton)ControlDictionary["largeIconsRadioButton"]).FlatStyle = FlatStyle.Standard; ((RadioButton)ControlDictionary["largeIconsRadioButton"]).Image = IconService.GetBitmap("Icons.16x16.LargeIconsIcon"); ((RadioButton)ControlDictionary["smallIconsRadioButton"]).Checked = !PropertyService.Get("Dialogs.NewProjectDialog.LargeImages", true); ((RadioButton)ControlDictionary["smallIconsRadioButton"]).CheckedChanged += new EventHandler(CheckedChange); ((RadioButton)ControlDictionary["smallIconsRadioButton"]).FlatStyle = FlatStyle.Standard; ((RadioButton)ControlDictionary["smallIconsRadioButton"]).Image = IconService.GetBitmap("Icons.16x16.SmallIconsIcon"); ToolTip tooltip = new ToolTip(); tooltip.SetToolTip(ControlDictionary["largeIconsRadioButton"], StringParser.Parse("${res:Global.LargeIconToolTip}")); tooltip.SetToolTip(ControlDictionary["smallIconsRadioButton"], StringParser.Parse("${res:Global.SmallIconToolTip}")); tooltip.Active = true; Owner = (Form)WorkbenchSingleton.Workbench; StartPosition = FormStartPosition.CenterParent; Icon = null; CheckedChange(this, EventArgs.Empty); } } }