Browse Source

Added search and other niceties.

pull/517/head^2
Ciprian Khlud 11 years ago
parent
commit
5af1dd8a4b
  1. 2
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  2. 14
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs
  3. 6
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs
  4. 167
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs
  5. 30
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml
  6. 96
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs

2
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -297,7 +297,7 @@ @@ -297,7 +297,7 @@
</Compile>
<Compile Include="Src\Gui\Dialogs\NewFileCategory.cs" />
<Compile Include="Src\Gui\Dialogs\ExtractInterfaceDialog.cs" />
<Compile Include="Src\Gui\Dialogs\NewFileTemplateItem.cs" />
<Compile Include="Src\Gui\Dialogs\NewFileTemplate.cs" />
<Compile Include="Src\Gui\Dialogs\NewFileViewModel.cs" />
<Compile Include="Src\Gui\Dialogs\NewFileWindow.xaml.cs">
<DependentUpon>NewFileWindow.xaml</DependentUpon>

14
src/Main/Base/Project/Src/Gui/Dialogs/NewFileCategory.cs

@ -1,21 +1,22 @@ @@ -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<NewFileCategory>();
Templates = new ObservableCollection<NewFileTemplateItem>();
DisplayName = displayName;
Templates = new ObservableCollection<NewFileTemplate>();
DisplayName = StringParser.Parse(displayName);
}
public ObservableCollection<NewFileCategory> Children { get; set; }
public ObservableCollection<NewFileTemplateItem> Templates { get; set; }
public ObservableCollection<NewFileTemplate> Templates { get; set; }
public string DisplayName
{
@ -26,10 +27,5 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -26,10 +27,5 @@ namespace ICSharpCode.SharpDevelop.Gui
OnPropertyChanged();
}
}
public bool IsEmpty
{
get { return Children.Count == 0; }
}
}
}

6
src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplateItem.cs → src/Main/Base/Project/Src/Gui/Dialogs/NewFileTemplate.cs

@ -6,14 +6,16 @@ using ICSharpCode.SharpDevelop.Widgets; @@ -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);

167
src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs

@ -9,8 +9,10 @@ @@ -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 @@ -23,16 +25,16 @@ namespace ICSharpCode.SharpDevelop.Gui
#region Backing properties
private NewFileCategory _selectedCategory;
private string _searchFor;
private ObservableCollection<NewFileTemplateItem> _allTemplate;
private NewFileTemplateItem _selectedItem;
private ObservableCollection<NewFileTemplate> _allTemplate;
private NewFileTemplate _selectedItem;
private string _fileName;
#endregion
public NewFileViewModel()
{
_allTemplate = new ObservableCollection<NewFileTemplateItem>();
_allTemplate = new ObservableCollection<NewFileTemplate>();
Icons = new Dictionary<IImage, int>();
Categories = new ObservableCollection<NewFileCategory>();
AllFileTemplates = new NewFileCategory("All");
@ -52,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -52,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Gui
}
public ObservableCollection<NewFileTemplateItem> SelectedTemplates
public ObservableCollection<NewFileTemplate> SelectedTemplates
{
get
{
@ -65,16 +67,38 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -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)
{
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 NewFileTemplateItem SelectedItem
public NewFileTemplate SelectedItem
{
get { return _selectedItem; }
set
@ -82,6 +106,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -82,6 +106,7 @@ namespace ICSharpCode.SharpDevelop.Gui
_selectedItem = value;
OnPropertyChanged();
OnPropertyChanged("Description");
FileName = GenerateCurrentFileName();
}
}
@ -103,15 +128,127 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -103,15 +128,127 @@ namespace ICSharpCode.SharpDevelop.Gui
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 { 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 @@ -125,16 +262,8 @@ namespace ICSharpCode.SharpDevelop.Gui
set { }
}
public Dictionary<IImage, int> Icons
{
get;
set;
}
public ObservableCollection<NewFileCategory> Categories { get; set; }
public ObservableCollection<NewFileCategory> Templates { get; set; }
}
}

30
src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml

@ -4,13 +4,13 @@ @@ -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">
<Window.DataContext>
<gui:NewFileViewModel />
</Window.DataContext>
<Grid>
<Grid Margin="4">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
</Grid.RowDefinitions>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="250" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions >
@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
<TreeView Grid.Row="1"
ItemsSource="{Binding Categories}"
x:Name="categoryTreeView"
HorizontalAlignment="Stretch"
SelectedItemChanged="CategoryTreeView_SelectedItemChanged"
>
@ -50,20 +51,33 @@ @@ -50,20 +51,33 @@
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="Search:" VerticalAlignment="Center" />
<TextBox Text="{Binding SearchFor}" Margin="2" Width="100"></TextBox>
<TextBox Text="{Binding SearchFor}" x:Name="SearchTextBox" Margin="2" Width="100" TextChanged="OnUpdateSearch" />
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding SelectedTemplates}"
SelectedItem="{Binding SelectedItem}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Picture}" Width="32" />
<StackPanel>
<StackPanel
Grid.Column="1"
HorizontalAlignment="Stretch"
>
<Label Content="{Binding DisplayName}" FontWeight="Bold" />
<Label Content="{Binding Description}" />
</StackPanel>
</StackPanel>
<Label Grid.Column="2"
Foreground="DarkGray"
HorizontalAlignment="Right"
Content="{Binding CategoryDescription}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

96
src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs

@ -23,7 +23,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -23,7 +23,7 @@ namespace ICSharpCode.SharpDevelop.Gui
/// <summary>
/// Interaction logic for NewFileWindow.xaml
/// </summary>
public partial class NewFileWindow : Window
public partial class NewFileWindow
{
public NewFileViewModel ViewModel
{
@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.Gui
public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable<TemplateCategory> templateCategories)
{
DataContext = new NewFileViewModel();
InitializeComponent();
ViewModel.Project = project;
ViewModel.BasePath = basePath;
@ -52,102 +53,31 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -52,102 +53,31 @@ namespace ICSharpCode.SharpDevelop.Gui
fileNameTextBox.Focus();
}
InitializeTemplates(templateCategories, ViewModel.Categories);
}
void InitializeTemplates(IEnumerable<TemplateCategory> templateCategories, ObservableCollection<NewFileCategory> categories)
{
foreach (var templateCategory in Sorted(templateCategories)) {
var cat = CreateCategory(templateCategory);
categories.Add(cat);
}
}
IEnumerable<TemplateCategory> Sorted(IEnumerable<TemplateCategory> 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<FileTemplate>())
{
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);
ViewModel.InitializeTemplates(templateCategories);
}
return node;
}
private void okButtonClick(object sender, RoutedEventArgs e)
{
var selectedTemplate = ViewModel.SelectedItem;
var fileName = ViewModel.FileName;
var standardNamespace = "DefaultNamespace";
var localizedTypeDescriptor = selectedTemplate.Template.CreateCustomizationObject();
var options = new FileTemplateOptions
void okButtonClick(object sender, RoutedEventArgs e)
{
ClassName =
GenerateValidClassOrNamespaceName(Path.GetFileNameWithoutExtension(ViewModel.FileName), false),
FileName = FileName.Create(fileName),
IsUntitled = ViewModel.AllowUntitledFiles,
Namespace = standardNamespace,
CustomizationObject = localizedTypeDescriptor,
Project = ViewModel.Project
};
var result = ViewModel.BuildSelectedResult();
ViewModel.Result = result;
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)
void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
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();
ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem;
ViewModel.UpdatedSelection();
}
void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
private void OnUpdateSearch(object sender, TextChangedEventArgs e)
{
ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem;
ViewModel.SearchFor = SearchTextBox.Text;
ViewModel.UpdatedSelection();
}
}

Loading…
Cancel
Save