diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
index 5d66a4ac4e..1c8087f936 100644
--- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
+++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
@@ -275,7 +275,9 @@
Code
-
+
+ UserControl
+
StringListEditorDialog.xaml
@@ -284,15 +286,26 @@
Code
-
+
+ Form
+
AsynchronousWaitDialog.cs
-
+
+ Form
+
AbstractAttachToProcessForm.cs
+
+
+
+
+ NewFileWindow.xaml
+ Code
+
OutputWindowOptionsPanel.xaml
Code
@@ -422,10 +435,10 @@
ExtractInterfaceDialog.cs
-
+
+
Form
-
NewProjectDialog.cs
@@ -548,11 +561,15 @@
-
+
+ Form
+
ToolNotFoundDialog.cs
-
+
+ UserControl
+
TabbedOptionsDialog.xaml
Code
@@ -669,11 +686,9 @@
UserControl
-
- UserControl
-
+
- Form
+ UserControl
Form
@@ -681,9 +696,7 @@
UserControl
-
- Form
-
+
Form
@@ -694,7 +707,7 @@
Component
- Component
+ UserControl
Component
@@ -819,7 +832,6 @@
- UserControl
BuildEvents.xaml
@@ -843,12 +855,18 @@
-
+
+ Component
+
-
-
+
+ Form
+
+
+ UserControl
+
@@ -856,8 +874,12 @@
-
-
+
+ Form
+
+
+ Component
+
@@ -873,7 +895,9 @@
-
+
+ Component
+
@@ -890,22 +914,13 @@
-
-
-
-
-
-
-
-
-
-
+
@@ -974,27 +989,6 @@
ICSharpCode.Core
False
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
{7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}
ICSharpCode.Core.Presentation
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs
new file mode 100644
index 0000000000..31b46346d8
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs
@@ -0,0 +1,31 @@
+using System.Collections.ObjectModel;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Widgets;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ public class NewFileCategory : ViewModelBase
+ {
+ string _displayName;
+
+ public NewFileCategory(string displayName)
+ {
+ Children = new ObservableCollection();
+ Templates = new ObservableCollection();
+ DisplayName = StringParser.Parse(displayName);
+ }
+
+ public ObservableCollection Children { get; set; }
+ public ObservableCollection Templates { get; set; }
+
+ public string DisplayName
+ {
+ get { return _displayName; }
+ set
+ {
+ _displayName = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs
new file mode 100644
index 0000000000..5dd4cff2a3
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs
@@ -0,0 +1,30 @@
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Templates;
+using ICSharpCode.SharpDevelop.Widgets;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ public class NewFileTemplate : ViewModelBase
+ {
+ 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);
+ } }
+
+ public ImageSource Picture { get{
+ return Template.Icon.ImageSource;
+ }
+ }
+ public string Name { get { return Template.Name; } }
+ }
+}
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs
new file mode 100644
index 0000000000..3d87b7a6f0
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs
@@ -0,0 +1,269 @@
+/*
+ * Created by SharpDevelop.
+ * User: Ciprian Khlud
+ * Date: 7/19/2014
+ * Time: 10:52 PM
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+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;
+using ICSharpCode.SharpDevelop.Project;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ public class NewFileViewModel : ViewModelBase
+ {
+ #region Backing properties
+ private NewFileCategory _selectedCategory;
+ private string _searchFor;
+ private ObservableCollection _allTemplate;
+ private NewFileTemplate _selectedItem;
+ private string _fileName;
+
+ #endregion
+
+ public NewFileViewModel()
+ {
+ _allTemplate = new ObservableCollection();
+
+ Categories = new ObservableCollection();
+
+ AllFileTemplates = new NewFileCategory("All");
+ Categories.Add(AllFileTemplates);
+ }
+
+ public NewFileCategory AllFileTemplates { get; set; }
+
+ public NewFileCategory SelectedCategory
+ {
+ get { return _selectedCategory; }
+ set
+ {
+ _selectedCategory = value;
+ OnPropertyChanged();
+ }
+ }
+
+
+ public ObservableCollection SelectedTemplates
+ {
+ get
+ {
+ UpdatedSelection();
+ return _allTemplate;
+ }
+ }
+
+ public void UpdatedSelection()
+ {
+ _allTemplate.Clear();
+ var selectedCategory = _selectedCategory;
+ if (selectedCategory == null) return;
+ var searchTokens = SearchFor.Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
+ foreach (var item in selectedCategory.Templates)
+ {
+ if(PassFilter(item, searchTokens))
+ _allTemplate.Add(item);
+ }
+ }
+
+ 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
+ {
+ _selectedItem = value;
+ OnPropertyChanged();
+ OnPropertyChanged("Description");
+ FileName = GenerateCurrentFileName();
+ }
+ }
+
+ public IProject Project
+ {
+ get;
+ set;
+ }
+
+ public DirectoryName BasePath
+ {
+ get;
+ set;
+ }
+
+ public bool AllowUntitledFiles
+ {
+ 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
+ {
+ if (string.IsNullOrEmpty(_searchFor))
+ _searchFor = string.Empty;
+ return _searchFor;
+ }
+ set
+ {
+ _searchFor = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string FileName
+ {
+ get { return _fileName; }
+ set
+ {
+ _fileName = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ return SelectedItem == null
+ ? string.Empty
+ : SelectedItem.Description;
+
+ }
+ set { }
+ }
+
+ public ObservableCollection Categories { get; set; }
+
+ }
+}
+
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml
new file mode 100644
index 0000000000..638013d480
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs
new file mode 100644
index 0000000000..bb4c0b4a20
--- /dev/null
+++ b/src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs
@@ -0,0 +1,84 @@
+/*
+ * Created by SharpDevelop.
+ * User: Ciprian Khlud
+ * Date: 7/19/2014
+ * Time: 10:52 PM
+ *
+ * To change this template use Tools | Options | Coding | Edit Standard Headers.
+ */
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using ICSharpCode.Core;
+using ICSharpCode.SharpDevelop.Project;
+using ICSharpCode.SharpDevelop.Templates;
+
+namespace ICSharpCode.SharpDevelop.Gui
+{
+ ///
+ /// Interaction logic for NewFileWindow.xaml
+ ///
+ public partial class NewFileWindow
+ {
+ public NewFileViewModel ViewModel
+ {
+ get
+ {
+ return (NewFileViewModel)DataContext;
+ }
+ }
+ public NewFileWindow()
+ {
+ InitializeComponent();
+ }
+ public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable templateCategories)
+ {
+ DataContext = new NewFileViewModel();
+
+ InitializeComponent();
+ ViewModel.Project = project;
+ ViewModel.BasePath = basePath;
+ ViewModel.AllowUntitledFiles = basePath == null;
+ if(ViewModel.AllowUntitledFiles)
+ {
+ categoryTreeView.Focus();
+ }
+ else
+ {
+ fileNameTextBox.Focus();
+ }
+
+ ViewModel.InitializeTemplates(templateCategories);
+ }
+ void okButtonClick(object sender, RoutedEventArgs e)
+ {
+ var result = ViewModel.BuildSelectedResult();
+ ViewModel.Result = result;
+
+ DialogResult = result!=null;
+ Close();
+ }
+
+ void cancelButtonClick(object sender, RoutedEventArgs e)
+ {
+ Close();
+ }
+
+ void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs
-
+
+ Component
+
Component
-
-
+
+ Component
+
+
+ Component
+
Form
-
-
+
+ Form
+
+
+ Form
+
Form
@@ -84,11 +94,15 @@
Component
-
+
+ Component
+
Component
-
+
+ Component
+
Component
diff --git a/src/Main/SharpDevelop/Services/UIService.cs b/src/Main/SharpDevelop/Services/UIService.cs
index 66a96bb013..38bfdfc017 100644
--- a/src/Main/SharpDevelop/Services/UIService.cs
+++ b/src/Main/SharpDevelop/Services/UIService.cs
@@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
+//#define EXPERIMENTAL_NEW_FILE
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -49,6 +51,17 @@ namespace ICSharpCode.SharpDevelop
#if DEBUG
SD.Templates.UpdateTemplates();
#endif
+ #if EXPERIMENTAL_NEW_FILE
+ var nfdWpf = new NewFileWindow(project, directory, templates ?? SD.Templates.TemplateCategories);
+ if (nfdWpf.ShowDialog() ?? false)
+ {
+ return nfdWpf.ViewModel.Result;
+ }
+ else
+ {
+ return null;
+ }
+ #endif
using (NewFileDialog nfd = new NewFileDialog(project, directory, templates ?? SD.Templates.TemplateCategories)) {
if (nfd.ShowDialog(SD.WinForms.MainWin32Window) == DialogResult.OK)
return nfd.result;