diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index 90310508d9..bd41b72de4 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -297,7 +297,7 @@ - + NewFileWindow.xaml diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs index 9794e5df56..31b46346d8 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs @@ -1,21 +1,22 @@ using System.Collections.ObjectModel; +using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Widgets; namespace ICSharpCode.SharpDevelop.Gui { public class NewFileCategory : ViewModelBase { - private string _displayName; + string _displayName; public NewFileCategory(string displayName) { Children = new ObservableCollection(); - Templates = new ObservableCollection(); - DisplayName = displayName; + Templates = new ObservableCollection(); + DisplayName = StringParser.Parse(displayName); } public ObservableCollection Children { get; set; } - public ObservableCollection Templates { get; set; } + public ObservableCollection Templates { get; set; } public string DisplayName { @@ -26,10 +27,5 @@ namespace ICSharpCode.SharpDevelop.Gui OnPropertyChanged(); } } - - public bool IsEmpty - { - get { return Children.Count == 0; } - } } } \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplateItem.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs similarity index 74% rename from src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplateItem.cs rename to src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs index ee741715df..5dd4cff2a3 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplateItem.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs @@ -6,14 +6,16 @@ using ICSharpCode.SharpDevelop.Widgets; namespace ICSharpCode.SharpDevelop.Gui { - public class NewFileTemplateItem : ViewModelBase + public class NewFileTemplate : ViewModelBase { - public NewFileTemplateItem(FileTemplate template) + public NewFileTemplate(FileTemplate template, string categoryDescription) { Template = template; + CategoryDescription = categoryDescription; } public FileTemplate Template { get; private set; } + public string CategoryDescription { get; set; } public string DisplayName { get { return Template.DisplayName; } } public string Description { get { return StringParser.Parse(Template.Description); diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs index bd4e7adc8b..3d87b7a6f0 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs @@ -9,8 +9,10 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.IO; using System.Linq; using System.Runtime.CompilerServices; +using System.Text; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Templates; using ICSharpCode.SharpDevelop.Widgets; @@ -23,16 +25,16 @@ namespace ICSharpCode.SharpDevelop.Gui #region Backing properties private NewFileCategory _selectedCategory; private string _searchFor; - private ObservableCollection _allTemplate; - private NewFileTemplateItem _selectedItem; + private ObservableCollection _allTemplate; + private NewFileTemplate _selectedItem; + private string _fileName; #endregion public NewFileViewModel() { - _allTemplate = new ObservableCollection(); + _allTemplate = new ObservableCollection(); - Icons = new Dictionary(); Categories = new ObservableCollection(); AllFileTemplates = new NewFileCategory("All"); @@ -52,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Gui } - public ObservableCollection SelectedTemplates + public ObservableCollection SelectedTemplates { get { @@ -65,16 +67,38 @@ namespace ICSharpCode.SharpDevelop.Gui { _allTemplate.Clear(); var selectedCategory = _selectedCategory; - if (selectedCategory != null) + if (selectedCategory == null) return; + var searchTokens = SearchFor.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in selectedCategory.Templates) { - foreach (var item in selectedCategory.Templates) - { + if(PassFilter(item, searchTokens)) _allTemplate.Add(item); - } } } - public NewFileTemplateItem SelectedItem + static bool PassFilter(NewFileTemplate template, string[] searchTokens) + { + if (searchTokens.Length == 0) + return true; + + var result = TextMatchesSearchTokens(searchTokens, template.DisplayName); + var resultDescription = TextMatchesSearchTokens(searchTokens, template.Description); + var resultCategory = TextMatchesSearchTokens(searchTokens, template.CategoryDescription); + + return result ||resultDescription || resultCategory; + } + + static bool TextMatchesSearchTokens(string[] searchTokens, string textToSearch) + { + foreach (var searchToken in searchTokens) + { + if (textToSearch.IndexOf(searchToken, StringComparison.OrdinalIgnoreCase) >= 0) + return true; + } + return false; + } + + public NewFileTemplate SelectedItem { get { return _selectedItem; } set @@ -82,6 +106,7 @@ namespace ICSharpCode.SharpDevelop.Gui _selectedItem = value; OnPropertyChanged(); OnPropertyChanged("Description"); + FileName = GenerateCurrentFileName(); } } @@ -102,16 +127,128 @@ namespace ICSharpCode.SharpDevelop.Gui get; set; } + + string GenerateCurrentFileName() + { + if(SelectedItem==null) + return string.Empty; + return SelectedItem.Template.SuggestFileName(BasePath); + } + + internal static string GenerateValidClassOrNamespaceName(string className, bool allowDot) + { + if (className == null) + throw new ArgumentNullException("className"); + className = className.Trim(); + if (className.Length == 0) + return string.Empty; + var nameBuilder = new StringBuilder(); + if (className[0] != '_' && !char.IsLetter(className, 0)) + nameBuilder.Append('_'); + for (int idx = 0; idx < className.Length; ++idx) + { + if (Char.IsLetterOrDigit(className[idx]) || className[idx] == '_') + { + nameBuilder.Append(className[idx]); + } + else if (className[idx] == '.' && allowDot) + { + nameBuilder.Append('.'); + } + else + { + nameBuilder.Append('_'); + } + } + return nameBuilder.ToString(); + } + + internal void InitializeTemplates(IEnumerable templateCategories) + { + var categories = Categories; + foreach (var templateCategory in Sorted(templateCategories)) { + var cat = CreateCategory(templateCategory); + categories.Add(cat); + } + SelectedCategory = AllFileTemplates; + } + + IEnumerable Sorted(IEnumerable templateCategories) + { + return templateCategories + .OrderByDescending(c => c.SortOrder) + .ThenBy(c => StringParser.Parse(c.DisplayName)); + } + NewFileCategory CreateCategory(TemplateCategory templateCategory) + { + var category = new NewFileCategory(templateCategory.DisplayName); + foreach (var subcategory in Sorted(templateCategory.Subcategories)) + { + var subnode = CreateCategory(subcategory); + category.Children.Add(subnode); + } + foreach (var template in templateCategory.Templates.OfType()) + { + if (!template.IsVisible(Project)) + continue; + var titem = new NewFileTemplate(template, category.DisplayName); + AllFileTemplates.Templates.Add(titem); + category.Templates.Add(titem); + } + return category; + } + + internal FileTemplateResult BuildSelectedResult() + { + var selectedTemplate = SelectedItem; + var fileName = FileName; + + var standardNamespace = "DefaultNamespace"; + + var localizedTypeDescriptor = selectedTemplate.Template.CreateCustomizationObject(); + var options = new FileTemplateOptions + { + ClassName = + GenerateValidClassOrNamespaceName(Path.GetFileNameWithoutExtension(FileName), false), + FileName = Core.FileName.Create(fileName), + IsUntitled = AllowUntitledFiles, + Namespace = standardNamespace, + CustomizationObject = localizedTypeDescriptor, + Project = Project + }; + + var result = selectedTemplate.Template.Create(options); + if (result != null) + selectedTemplate.Template.RunActions(result); + return result; + } public FileTemplateResult Result { get;set; } public string SearchFor { - get { return _searchFor; } - set { _searchFor = value; } + get + { + if (string.IsNullOrEmpty(_searchFor)) + _searchFor = string.Empty; + return _searchFor; + } + set + { + _searchFor = value; + OnPropertyChanged(); + } } - public string FileName { get; set; } + public string FileName + { + get { return _fileName; } + set + { + _fileName = value; + OnPropertyChanged(); + } + } public string Description { @@ -125,16 +262,8 @@ namespace ICSharpCode.SharpDevelop.Gui set { } } - - public Dictionary Icons - { - get; - set; - } - public ObservableCollection Categories { get; set; } - public ObservableCollection Templates { get; set; } } } diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml index d4abb5814b..2947d10252 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml @@ -4,13 +4,13 @@ xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" xmlns:core="http://icsharpcode.net/sharpdevelop/core" - Title="ICSharpCode.SharpDevelop.Gui" + Title="${res:Dialog.NewFile.DialogName}" WindowStartupLocation="CenterScreen" - Height="300" Width="500"> + Height="400" Width="600"> - + @@ -18,7 +18,7 @@ - + @@ -31,6 +31,7 @@ @@ -50,20 +51,33 @@ - + - + + + + + + - + - + diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs index 6ba931ee99..bb4c0b4a20 100644 --- a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs +++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs @@ -23,8 +23,8 @@ namespace ICSharpCode.SharpDevelop.Gui /// /// Interaction logic for NewFileWindow.xaml /// - public partial class NewFileWindow : Window - { + public partial class NewFileWindow + { public NewFileViewModel ViewModel { get @@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.Gui public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable templateCategories) { DataContext = new NewFileViewModel(); + InitializeComponent(); ViewModel.Project = project; ViewModel.BasePath = basePath; @@ -52,103 +53,32 @@ namespace ICSharpCode.SharpDevelop.Gui fileNameTextBox.Focus(); } - InitializeTemplates(templateCategories, ViewModel.Categories); + ViewModel.InitializeTemplates(templateCategories); } - - void InitializeTemplates(IEnumerable templateCategories, ObservableCollection categories) - { - foreach (var templateCategory in Sorted(templateCategories)) { - var cat = CreateCategory(templateCategory); - categories.Add(cat); - } - } - - IEnumerable Sorted(IEnumerable templateCategories) - { - return templateCategories.OrderByDescending(c => c.SortOrder).ThenBy(c => StringParser.Parse(c.DisplayName)); - } - - NewFileCategory CreateCategory(TemplateCategory templateCategory) - { - var node = new NewFileCategory(templateCategory.DisplayName); - foreach (var subcategory in Sorted(templateCategory.Subcategories)) - { - var subnode = CreateCategory(subcategory); - node.Children.Add(subnode); - } - foreach (var template in templateCategory.Templates.OfType()) - { - if (!template.IsVisible(ViewModel.Project)) - continue; - var titem = new NewFileTemplateItem(template); - if (titem.Template.Icon != null) - { - ViewModel.Icons[titem.Template.Icon] = 0; // "create template icon" - } - ViewModel.AllFileTemplates.Templates.Add(titem); - ViewModel.SelectedTemplates.Add(titem); - node.Templates.Add(titem); - } - return node; - } - private void okButtonClick(object sender, RoutedEventArgs e) + void okButtonClick(object sender, RoutedEventArgs e) { + var result = ViewModel.BuildSelectedResult(); + ViewModel.Result = result; - var selectedTemplate = ViewModel.SelectedItem; - var fileName = ViewModel.FileName; - - var standardNamespace = "DefaultNamespace"; - - var localizedTypeDescriptor = selectedTemplate.Template.CreateCustomizationObject(); - var options = new FileTemplateOptions - { - ClassName = - GenerateValidClassOrNamespaceName(Path.GetFileNameWithoutExtension(ViewModel.FileName), false), - FileName = FileName.Create(fileName), - IsUntitled = ViewModel.AllowUntitledFiles, - Namespace = standardNamespace, - CustomizationObject = localizedTypeDescriptor, - Project = ViewModel.Project - }; - - var result = selectedTemplate.Template.Create(options); - DialogResult = true; - if (result != null) - selectedTemplate.Template.RunActions(result); + DialogResult = result!=null; Close(); } - private void cancelButtonClick(object sender, RoutedEventArgs e) + void cancelButtonClick(object sender, RoutedEventArgs e) { Close(); } - internal static string GenerateValidClassOrNamespaceName(string className, bool allowDot) - { - if (className == null) - throw new ArgumentNullException("className"); - className = className.Trim(); - if (className.Length == 0) - return string.Empty; - StringBuilder nameBuilder = new StringBuilder(); - if (className[0] != '_' && !char.IsLetter(className, 0)) - nameBuilder.Append('_'); - for (int idx = 0; idx < className.Length; ++idx) { - if (Char.IsLetterOrDigit(className[idx]) || className[idx] == '_') { - nameBuilder.Append(className[idx]); - } else if (className[idx] == '.' && allowDot) { - nameBuilder.Append('.'); - } else { - nameBuilder.Append('_'); - } - } - return nameBuilder.ToString(); - } - void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs e) { ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem; ViewModel.UpdatedSelection(); } - } + + private void OnUpdateSearch(object sender, TextChangedEventArgs e) + { + ViewModel.SearchFor = SearchTextBox.Text; + ViewModel.UpdatedSelection(); + } + } } \ No newline at end of file