8 changed files with 608 additions and 60 deletions
@ -0,0 +1,31 @@
@@ -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<NewFileCategory>(); |
||||
Templates = new ObservableCollection<NewFileTemplate>(); |
||||
DisplayName = StringParser.Parse(displayName); |
||||
} |
||||
|
||||
public ObservableCollection<NewFileCategory> Children { get; set; } |
||||
public ObservableCollection<NewFileTemplate> Templates { get; set; } |
||||
|
||||
public string DisplayName |
||||
{ |
||||
get { return _displayName; } |
||||
set |
||||
{ |
||||
_displayName = value; |
||||
OnPropertyChanged(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,30 @@
@@ -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; } } |
||||
} |
||||
} |
@ -0,0 +1,269 @@
@@ -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<NewFileTemplate> _allTemplate; |
||||
private NewFileTemplate _selectedItem; |
||||
private string _fileName; |
||||
|
||||
#endregion
|
||||
|
||||
public NewFileViewModel() |
||||
{ |
||||
_allTemplate = new ObservableCollection<NewFileTemplate>(); |
||||
|
||||
Categories = new ObservableCollection<NewFileCategory>(); |
||||
|
||||
AllFileTemplates = new NewFileCategory("All"); |
||||
Categories.Add(AllFileTemplates); |
||||
} |
||||
|
||||
public NewFileCategory AllFileTemplates { get; set; } |
||||
|
||||
public NewFileCategory SelectedCategory |
||||
{ |
||||
get { return _selectedCategory; } |
||||
set |
||||
{ |
||||
_selectedCategory = value; |
||||
OnPropertyChanged(); |
||||
} |
||||
} |
||||
|
||||
|
||||
public ObservableCollection<NewFileTemplate> 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<TemplateCategory> templateCategories) |
||||
{ |
||||
var categories = Categories; |
||||
foreach (var templateCategory in Sorted(templateCategories)) { |
||||
var cat = CreateCategory(templateCategory); |
||||
categories.Add(cat); |
||||
} |
||||
SelectedCategory = AllFileTemplates; |
||||
} |
||||
|
||||
IEnumerable<TemplateCategory> Sorted(IEnumerable<TemplateCategory> 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<FileTemplate>()) |
||||
{ |
||||
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<NewFileCategory> Categories { get; set; } |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
<Window x:Class="ICSharpCode.SharpDevelop.Gui.NewFileWindow" |
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui" |
||||
xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" |
||||
xmlns:core="http://icsharpcode.net/sharpdevelop/core" |
||||
Title="${res:Dialog.NewFile.DialogName}" |
||||
WindowStartupLocation="CenterScreen" |
||||
Height="400" Width="600"> |
||||
<Window.DataContext> |
||||
<gui:NewFileViewModel /> |
||||
</Window.DataContext> |
||||
<Grid Margin="4"> |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto"/> |
||||
<RowDefinition /> |
||||
<RowDefinition Height="Auto"/> |
||||
</Grid.RowDefinitions> |
||||
<Grid Grid.Row="1"> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="250" /> |
||||
<ColumnDefinition Width="5" /> |
||||
<ColumnDefinition Width="*" /> |
||||
</Grid.ColumnDefinitions > |
||||
<Grid > |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto" /> |
||||
<RowDefinition /> |
||||
</Grid.RowDefinitions> |
||||
<TextBlock Text="Categories" /> |
||||
<TreeView Grid.Row="1" |
||||
ItemsSource="{Binding Categories}" |
||||
x:Name="categoryTreeView" |
||||
HorizontalAlignment="Stretch" |
||||
SelectedItemChanged="CategoryTreeView_SelectedItemChanged" |
||||
> |
||||
|
||||
<TreeView.ItemTemplate> |
||||
<HierarchicalDataTemplate ItemsSource="{Binding Children}"> |
||||
<TextBlock Text="{Binding DisplayName}" /> |
||||
</HierarchicalDataTemplate> |
||||
</TreeView.ItemTemplate> |
||||
|
||||
</TreeView> |
||||
</Grid> |
||||
<GridSplitter Grid.Column="1" ResizeDirection="Columns" Width="5" HorizontalAlignment="Center" VerticalAlignment="Stretch"/> |
||||
<Grid Grid.Column="2" > |
||||
<Grid.RowDefinitions> |
||||
<RowDefinition Height="Auto" /> |
||||
<RowDefinition Height="*" /> |
||||
</Grid.RowDefinitions> |
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> |
||||
<TextBlock Text="Search:" VerticalAlignment="Center" /> |
||||
<TextBox Text="{Binding SearchFor}" x:Name="SearchTextBox" Margin="2" Width="100" TextChanged="OnUpdateSearch" /> |
||||
</StackPanel> |
||||
<ListBox Grid.Row="1" ItemsSource="{Binding SelectedTemplates}" |
||||
SelectedItem="{Binding SelectedItem}" |
||||
Grid.IsSharedSizeScope="True" |
||||
> |
||||
<ListBox.ItemTemplate> |
||||
<DataTemplate> |
||||
<Grid > |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Column1" /> |
||||
<ColumnDefinition SharedSizeGroup="Column2" /> |
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="Column3" /> |
||||
</Grid.ColumnDefinitions> |
||||
<Image Source="{Binding Picture}" Width="32" /> |
||||
<StackPanel |
||||
Grid.Column="1" |
||||
HorizontalAlignment="Stretch" |
||||
> |
||||
<Label Content="{Binding DisplayName}" FontWeight="Bold" /> |
||||
<Label Content="{Binding Description}" /> |
||||
</StackPanel> |
||||
<Label Grid.Column="2" |
||||
Foreground="DarkGray" |
||||
HorizontalAlignment="Right" |
||||
Content="{Binding CategoryDescription}"/> |
||||
</Grid> |
||||
</DataTemplate> |
||||
</ListBox.ItemTemplate> |
||||
</ListBox> |
||||
</Grid> |
||||
</Grid> |
||||
|
||||
<StackPanel Grid.Row="2"> |
||||
<Label Content="{Binding Description}" /> |
||||
<Grid> |
||||
<Grid.ColumnDefinitions> |
||||
<ColumnDefinition Width="Auto" /> |
||||
<ColumnDefinition /> |
||||
</Grid.ColumnDefinitions> |
||||
<TextBlock Text="File name: " VerticalAlignment="Center" /> |
||||
<TextBox Grid.Column="1" Text="{Binding FileName}" x:Name="fileNameTextBox" /> |
||||
</Grid> |
||||
<widgets:UniformGridWithSpacing Columns="2" HorizontalAlignment="Right" Margin="0,4,12,12"> |
||||
<Button |
||||
Content="{core:Localize Global.OKButtonText}" |
||||
IsDefault="True" |
||||
Name="okButton" |
||||
Style="{x:Static core:GlobalStyles.ButtonStyle}" |
||||
Click="okButtonClick" /> |
||||
<Button |
||||
Content="{core:Localize Global.CancelButtonText}" |
||||
IsCancel="True" |
||||
Name="cancelButton" |
||||
Style="{x:Static core:GlobalStyles.ButtonStyle}" |
||||
Click="cancelButtonClick" /> |
||||
</widgets:UniformGridWithSpacing> |
||||
</StackPanel> |
||||
</Grid> |
||||
</Window> |
@ -0,0 +1,84 @@
@@ -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 |
||||
{ |
||||
/// <summary>
|
||||
/// Interaction logic for NewFileWindow.xaml
|
||||
/// </summary>
|
||||
public partial class NewFileWindow |
||||
{ |
||||
public NewFileViewModel ViewModel |
||||
{ |
||||
get |
||||
{ |
||||
return (NewFileViewModel)DataContext; |
||||
} |
||||
} |
||||
public NewFileWindow() |
||||
{ |
||||
InitializeComponent(); |
||||
} |
||||
public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable<TemplateCategory> 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<object> e) |
||||
{ |
||||
ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem; |
||||
ViewModel.UpdatedSelection(); |
||||
} |
||||
|
||||
private void OnUpdateSearch(object sender, TextChangedEventArgs e) |
||||
{ |
||||
ViewModel.SearchFor = SearchTextBox.Text; |
||||
ViewModel.UpdatedSelection(); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue