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. 171
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileViewModel.cs
  5. 30
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml
  6. 102
      src/Main/Base/Project/Src/Gui/Dialogs/NewFileWindow.xaml.cs

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

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

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

@ -1,21 +1,22 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Widgets; using ICSharpCode.SharpDevelop.Widgets;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Gui
{ {
public class NewFileCategory : ViewModelBase public class NewFileCategory : ViewModelBase
{ {
private string _displayName; string _displayName;
public NewFileCategory(string displayName) public NewFileCategory(string displayName)
{ {
Children = new ObservableCollection<NewFileCategory>(); Children = new ObservableCollection<NewFileCategory>();
Templates = new ObservableCollection<NewFileTemplateItem>(); Templates = new ObservableCollection<NewFileTemplate>();
DisplayName = displayName; DisplayName = StringParser.Parse(displayName);
} }
public ObservableCollection<NewFileCategory> Children { get; set; } public ObservableCollection<NewFileCategory> Children { get; set; }
public ObservableCollection<NewFileTemplateItem> Templates { get; set; } public ObservableCollection<NewFileTemplate> Templates { get; set; }
public string DisplayName public string DisplayName
{ {
@ -26,10 +27,5 @@ namespace ICSharpCode.SharpDevelop.Gui
OnPropertyChanged(); 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;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Gui
{ {
public class NewFileTemplateItem : ViewModelBase public class NewFileTemplate : ViewModelBase
{ {
public NewFileTemplateItem(FileTemplate template) public NewFileTemplate(FileTemplate template, string categoryDescription)
{ {
Template = template; Template = template;
CategoryDescription = categoryDescription;
} }
public FileTemplate Template { get; private set; } public FileTemplate Template { get; private set; }
public string CategoryDescription { get; set; }
public string DisplayName { get { return Template.DisplayName; } } public string DisplayName { get { return Template.DisplayName; } }
public string Description { get { public string Description { get {
return StringParser.Parse(Template.Description); return StringParser.Parse(Template.Description);

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

@ -9,8 +9,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Templates; using ICSharpCode.SharpDevelop.Templates;
using ICSharpCode.SharpDevelop.Widgets; using ICSharpCode.SharpDevelop.Widgets;
@ -23,16 +25,16 @@ namespace ICSharpCode.SharpDevelop.Gui
#region Backing properties #region Backing properties
private NewFileCategory _selectedCategory; private NewFileCategory _selectedCategory;
private string _searchFor; private string _searchFor;
private ObservableCollection<NewFileTemplateItem> _allTemplate; private ObservableCollection<NewFileTemplate> _allTemplate;
private NewFileTemplateItem _selectedItem; private NewFileTemplate _selectedItem;
private string _fileName;
#endregion #endregion
public NewFileViewModel() public NewFileViewModel()
{ {
_allTemplate = new ObservableCollection<NewFileTemplateItem>(); _allTemplate = new ObservableCollection<NewFileTemplate>();
Icons = new Dictionary<IImage, int>();
Categories = new ObservableCollection<NewFileCategory>(); Categories = new ObservableCollection<NewFileCategory>();
AllFileTemplates = new NewFileCategory("All"); AllFileTemplates = new NewFileCategory("All");
@ -52,7 +54,7 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
public ObservableCollection<NewFileTemplateItem> SelectedTemplates public ObservableCollection<NewFileTemplate> SelectedTemplates
{ {
get get
{ {
@ -65,16 +67,38 @@ namespace ICSharpCode.SharpDevelop.Gui
{ {
_allTemplate.Clear(); _allTemplate.Clear();
var selectedCategory = _selectedCategory; 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); _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; } get { return _selectedItem; }
set set
@ -82,6 +106,7 @@ namespace ICSharpCode.SharpDevelop.Gui
_selectedItem = value; _selectedItem = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged("Description"); OnPropertyChanged("Description");
FileName = GenerateCurrentFileName();
} }
} }
@ -102,16 +127,128 @@ namespace ICSharpCode.SharpDevelop.Gui
get; get;
set; 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 FileTemplateResult Result { get;set; }
public string SearchFor public string SearchFor
{ {
get { return _searchFor; } get
set { _searchFor = value; } {
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 public string Description
{ {
@ -125,16 +262,8 @@ namespace ICSharpCode.SharpDevelop.Gui
set { } set { }
} }
public Dictionary<IImage, int> Icons
{
get;
set;
}
public ObservableCollection<NewFileCategory> Categories { 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 @@
xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui" xmlns:gui="clr-namespace:ICSharpCode.SharpDevelop.Gui"
xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets" xmlns:widgets="http://icsharpcode.net/sharpdevelop/widgets"
xmlns:core="http://icsharpcode.net/sharpdevelop/core" xmlns:core="http://icsharpcode.net/sharpdevelop/core"
Title="ICSharpCode.SharpDevelop.Gui" Title="${res:Dialog.NewFile.DialogName}"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Height="300" Width="500"> Height="400" Width="600">
<Window.DataContext> <Window.DataContext>
<gui:NewFileViewModel /> <gui:NewFileViewModel />
</Window.DataContext> </Window.DataContext>
<Grid> <Grid Margin="4">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/>
<RowDefinition /> <RowDefinition />
@ -18,7 +18,7 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="1"> <Grid Grid.Row="1">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="250" />
<ColumnDefinition Width="5" /> <ColumnDefinition Width="5" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions > </Grid.ColumnDefinitions >
@ -31,6 +31,7 @@
<TreeView Grid.Row="1" <TreeView Grid.Row="1"
ItemsSource="{Binding Categories}" ItemsSource="{Binding Categories}"
x:Name="categoryTreeView" x:Name="categoryTreeView"
HorizontalAlignment="Stretch"
SelectedItemChanged="CategoryTreeView_SelectedItemChanged" SelectedItemChanged="CategoryTreeView_SelectedItemChanged"
> >
@ -50,20 +51,33 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="Search:" VerticalAlignment="Center" /> <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> </StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding SelectedTemplates}" <ListBox Grid.Row="1" ItemsSource="{Binding SelectedTemplates}"
SelectedItem="{Binding SelectedItem}" SelectedItem="{Binding SelectedItem}"
> >
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal"> <Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Image Source="{Binding Picture}" Width="32" /> <Image Source="{Binding Picture}" Width="32" />
<StackPanel> <StackPanel
Grid.Column="1"
HorizontalAlignment="Stretch"
>
<Label Content="{Binding DisplayName}" FontWeight="Bold" /> <Label Content="{Binding DisplayName}" FontWeight="Bold" />
<Label Content="{Binding Description}" /> <Label Content="{Binding Description}" />
</StackPanel> </StackPanel>
</StackPanel> <Label Grid.Column="2"
Foreground="DarkGray"
HorizontalAlignment="Right"
Content="{Binding CategoryDescription}"/>
</Grid>
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
</ListBox> </ListBox>

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

@ -23,8 +23,8 @@ namespace ICSharpCode.SharpDevelop.Gui
/// <summary> /// <summary>
/// Interaction logic for NewFileWindow.xaml /// Interaction logic for NewFileWindow.xaml
/// </summary> /// </summary>
public partial class NewFileWindow : Window public partial class NewFileWindow
{ {
public NewFileViewModel ViewModel public NewFileViewModel ViewModel
{ {
get get
@ -39,6 +39,7 @@ namespace ICSharpCode.SharpDevelop.Gui
public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable<TemplateCategory> templateCategories) public NewFileWindow(IProject project, DirectoryName basePath, IEnumerable<TemplateCategory> templateCategories)
{ {
DataContext = new NewFileViewModel(); DataContext = new NewFileViewModel();
InitializeComponent(); InitializeComponent();
ViewModel.Project = project; ViewModel.Project = project;
ViewModel.BasePath = basePath; ViewModel.BasePath = basePath;
@ -52,103 +53,32 @@ namespace ICSharpCode.SharpDevelop.Gui
fileNameTextBox.Focus(); fileNameTextBox.Focus();
} }
InitializeTemplates(templateCategories, ViewModel.Categories); ViewModel.InitializeTemplates(templateCategories);
} }
void okButtonClick(object sender, RoutedEventArgs e)
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);
}
return node;
}
private void okButtonClick(object sender, RoutedEventArgs e)
{ {
var result = ViewModel.BuildSelectedResult();
ViewModel.Result = result;
var selectedTemplate = ViewModel.SelectedItem; DialogResult = result!=null;
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);
Close(); Close();
} }
private void cancelButtonClick(object sender, RoutedEventArgs e) void cancelButtonClick(object sender, RoutedEventArgs e)
{ {
Close(); 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<object> e) void CategoryTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{ {
ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem; ViewModel.SelectedCategory = (NewFileCategory)categoryTreeView.SelectedItem;
ViewModel.UpdatedSelection(); ViewModel.UpdatedSelection();
} }
}
private void OnUpdateSearch(object sender, TextChangedEventArgs e)
{
ViewModel.SearchFor = SearchTextBox.Text;
ViewModel.UpdatedSelection();
}
}
} }
Loading…
Cancel
Save