Skip to content

Commit 10ac1f0

Browse files
authored
Merge pull request #4225 from ThunderFrame/next
Adds Add Predeclared Class Module Command
2 parents 660797d + d0a638d commit 10ac1f0

22 files changed

+1008
-262
lines changed

Rubberduck.Core/App.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,8 @@ private void ApplyCultureConfig()
182182

183183
private static void LocalizeResources(CultureInfo culture)
184184
{
185+
//TODO: this method needs something better - maybe use reflection to discover all resourcees
186+
// to set culture for all resources files?
185187
Resources.RubberduckUI.Culture = culture;
186188
Resources.About.AboutUI.Culture = culture;
187189
Resources.Inspections.InspectionInfo.Culture = culture;
@@ -197,6 +199,7 @@ private static void LocalizeResources(CultureInfo culture)
197199
Resources.ToDoExplorer.ToDoExplorerUI.Culture = culture;
198200
Resources.UnitTesting.AssertMessages.Culture = culture;
199201
Resources.UnitTesting.TestExplorer.Culture = culture;
202+
Resources.Templates.Culture = culture;
200203
}
201204

202205
private void CheckForLegacyIndenterSettings()

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerComponentViewModel.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.IO;
43
using System.Linq;
54
using System.Runtime.InteropServices;
65
using System.Windows.Media.Imaging;
7-
using NLog;
86
using Rubberduck.Parsing.Symbols;
97
using Rubberduck.VBEditor;
108
using Rubberduck.Parsing.Annotations;

Rubberduck.Core/Navigation/CodeExplorer/CodeExplorerViewModel.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Rubberduck.VBEditor.SafeComWrappers;
2020
using System.Windows;
2121
using Rubberduck.Parsing.UIContext;
22+
using Rubberduck.Templates;
2223
using Rubberduck.UI.UnitTesting.Commands;
2324
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
2425

@@ -36,7 +37,7 @@ public sealed class CodeExplorerViewModel : ViewModelBase, IDisposable
3637
private readonly WindowSettings _windowSettings;
3738
private readonly IUiDispatcher _uiDispatcher;
3839
private readonly IVBE _vbe;
39-
40+
private readonly ITemplateProvider _templateProvider;
4041
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
4142

4243
public CodeExplorerViewModel(
@@ -46,7 +47,8 @@ public CodeExplorerViewModel(
4647
IConfigProvider<GeneralSettings> generalSettingsProvider,
4748
IConfigProvider<WindowSettings> windowSettingsProvider,
4849
IUiDispatcher uiDispatcher,
49-
IVBE vbe)
50+
IVBE vbe,
51+
ITemplateProvider templateProvider)
5052
{
5153
_folderHelper = folderHelper;
5254
_state = state;
@@ -55,6 +57,7 @@ public CodeExplorerViewModel(
5557
_windowSettingsProvider = windowSettingsProvider;
5658
_uiDispatcher = uiDispatcher;
5759
_vbe = vbe;
60+
_templateProvider = templateProvider;
5861

5962
if (generalSettingsProvider != null)
6063
{
@@ -93,6 +96,14 @@ public CodeExplorerViewModel(
9396
}, param => !SortByCodeOrder);
9497
}
9598

99+
public ObservableCollection<Template> BuiltInTemplates =>
100+
new ObservableCollection<Template>(_templateProvider.GetTemplates().Where(t => !t.IsUserDefined)
101+
.OrderBy(t => t.Name));
102+
103+
public ObservableCollection<Template> UserDefinedTemplates =>
104+
new ObservableCollection<Template>(_templateProvider.GetTemplates().Where(t => t.IsUserDefined)
105+
.OrderBy(t => t.Name));
106+
96107
private CodeExplorerItemViewModel _selectedItem;
97108
public CodeExplorerItemViewModel SelectedItem
98109
{
@@ -533,27 +544,20 @@ public double FontSize
533544
public AddUserDocumentCommand AddUserDocumentCommand { get; set; }
534545
public AddTestModuleCommand AddTestModuleCommand { get; set; }
535546
public AddTestModuleWithStubsCommand AddTestModuleWithStubsCommand { get; set; }
536-
537-
public OpenDesignerCommand OpenDesignerCommand { get; set; }
547+
public AddTemplateCommand AddTemplateCommand { get; set; }
548+
public CommandBase OpenDesignerCommand { get; set; }
549+
public CommandBase OpenProjectPropertiesCommand { get; set; }
538550
public SetAsStartupProjectCommand SetAsStartupProjectCommand { get; set; }
539-
public OpenProjectPropertiesCommand OpenProjectPropertiesCommand { get; set; }
540-
541551
public RenameCommand RenameCommand { get; set; }
542-
543552
public IndentCommand IndenterCommand { get; set; }
544-
545553
public FindAllReferencesCommand FindAllReferencesCommand { get; set; }
546554
public FindAllImplementationsCommand FindAllImplementationsCommand { get; set; }
547-
548555
public CommandBase CollapseAllSubnodesCommand { get; }
549556
public CommandBase ExpandAllSubnodesCommand { get; }
550-
551557
public ImportCommand ImportCommand { get; set; }
552558
public ExportCommand ExportCommand { get; set; }
553559
public ExportAllCommand ExportAllCommand { get; set; }
554-
555560
public CommandBase RemoveCommand { get; }
556-
557561
public PrintCommand PrintCommand { get; set; }
558562

559563
private readonly RemoveCommand _externalRemoveCommand;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace Rubberduck.Templates
2+
{
3+
public interface ITemplate
4+
{
5+
string Name { get; }
6+
bool IsUserDefined { get; }
7+
string Caption { get; }
8+
string Description { get; }
9+
string Read();
10+
void Write(string content);
11+
}
12+
}

Rubberduck.Core/Templates/Template.cs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
namespace Rubberduck.Templates
2+
{
3+
/// <remarks>
4+
/// Template can be either built-in or user-defined. For a built-in template, the
5+
/// metadata should be stored in the <see cref="Rubberduck.Resources.Templates"/>
6+
/// resource, with specific entries, currently Name, Caption, Description and Code.
7+
/// Due to the fact that we cannot strong-type the reference to the resource entries
8+
/// the class has unit tests to validate that the crucial elements are present in the
9+
/// resource to guard against runtime errors/unexpected behavior due to missing/malformed
10+
/// entries in the resources.
11+
/// </remarks>
12+
public class Template : ITemplate
13+
{
14+
private readonly ITemplateFileHandler _handler;
15+
public Template(string name, ITemplateFileHandler handler)
16+
{
17+
_handler = handler;
18+
19+
Name = name;
20+
IsUserDefined = VerifyIfUserDefined(name);
21+
22+
if (IsUserDefined)
23+
{
24+
//TODO: Devise a way for users to define their captions/descriptions simply
25+
Caption = Name;
26+
Description = Name;
27+
}
28+
else
29+
{
30+
VerifyFile(name, handler);
31+
(Caption, Description) = GetBuiltInMetaData(name);
32+
}
33+
}
34+
35+
public string Name { get; }
36+
public bool IsUserDefined { get; }
37+
public string Caption { get; }
38+
public string Description { get; }
39+
40+
public string Read() => _handler.Read();
41+
42+
public void Write(string content) => _handler.Write(content);
43+
44+
private static bool VerifyIfUserDefined(string name)
45+
{
46+
var builtInName = Resources.Templates.ResourceManager.GetString(name + "_Name");
47+
return builtInName == null || builtInName != name;
48+
}
49+
50+
private static void VerifyFile(string name, ITemplateFileHandler handler)
51+
{
52+
if (handler.Exists)
53+
{
54+
return;
55+
}
56+
57+
var content = Resources.Templates.ResourceManager.GetString(name + "_Code");
58+
handler.Write(content);
59+
}
60+
61+
private static (string caption, string description) GetBuiltInMetaData(string name)
62+
{
63+
var caption = Resources.Templates.ResourceManager.GetString(name + "_Caption");
64+
var description = Resources.Templates.ResourceManager.GetString(name + "_Description");
65+
66+
return (caption, description);
67+
}
68+
}
69+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using Rubberduck.SettingsProvider;
6+
7+
namespace Rubberduck.Templates
8+
{
9+
public interface ITemplateFileHandlerProvider
10+
{
11+
ITemplateFileHandler CreateTemplateFileHandler(string templateName);
12+
IEnumerable<string> GetTemplateNames();
13+
}
14+
15+
public class TemplateFileHandlerProvider : ITemplateFileHandlerProvider
16+
{
17+
private readonly string _rootPath;
18+
19+
public TemplateFileHandlerProvider(IPersistancePathProvider pathProvider)
20+
{
21+
_rootPath = pathProvider.DataFolderPath("Templates");
22+
}
23+
24+
public ITemplateFileHandler CreateTemplateFileHandler(string templateName)
25+
{
26+
if (!Directory.Exists(_rootPath))
27+
{
28+
Directory.CreateDirectory(_rootPath);
29+
}
30+
31+
var fullPath = Path.Combine(_rootPath, templateName);
32+
if (!Directory.Exists(Path.GetDirectoryName(fullPath)))
33+
{
34+
throw new InvalidOperationException("Cannot provide a path for where the parent directory do not exist");
35+
}
36+
return new TemplateFileHandler(fullPath);
37+
}
38+
39+
public IEnumerable<string> GetTemplateNames()
40+
{
41+
var info = new DirectoryInfo(_rootPath);
42+
return info.GetFiles().Select(file => file.Name).ToList();
43+
}
44+
}
45+
46+
public interface ITemplateFileHandler
47+
{
48+
bool Exists { get; }
49+
string Read();
50+
void Write(string content);
51+
}
52+
53+
public class TemplateFileHandler : ITemplateFileHandler
54+
{
55+
private readonly string _fullPath;
56+
57+
public TemplateFileHandler(string fullPath)
58+
{
59+
_fullPath = fullPath + (fullPath.EndsWith(".rdt") ? string.Empty : ".rdt");
60+
}
61+
62+
public bool Exists => File.Exists(_fullPath);
63+
64+
public string Read()
65+
{
66+
return Exists ? File.ReadAllText(_fullPath) : null;
67+
}
68+
69+
public void Write(string content)
70+
{
71+
File.WriteAllText(_fullPath, content);
72+
}
73+
}
74+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Globalization;
5+
using System.Linq;
6+
7+
namespace Rubberduck.Templates
8+
{
9+
public interface ITemplateProvider
10+
{
11+
ITemplate Load(string templateName);
12+
IEnumerable<Template> GetTemplates();
13+
}
14+
15+
public class TemplateProvider : ITemplateProvider
16+
{
17+
private readonly ITemplateFileHandlerProvider _provider;
18+
19+
public TemplateProvider(ITemplateFileHandlerProvider provider)
20+
{
21+
_provider = provider;
22+
}
23+
24+
public ITemplate Load(string templateName)
25+
{
26+
var handler = _provider.CreateTemplateFileHandler(templateName);
27+
return new Template(templateName, handler);
28+
}
29+
30+
private Lazy<IEnumerable<Template>> LazyList => new Lazy<IEnumerable<Template>>(() =>
31+
{
32+
var list = new List<Template>();
33+
var set = Rubberduck.Resources.Templates.ResourceManager.GetResourceSet(CultureInfo.CurrentCulture, true, true);
34+
35+
foreach (DictionaryEntry entry in set)
36+
{
37+
var key = (string)entry.Key;
38+
var value = (string) entry.Value;
39+
if (key.EndsWith("_Name"))
40+
{
41+
var handler = _provider.CreateTemplateFileHandler(value);
42+
list.Add(new Template(value, handler));
43+
}
44+
}
45+
46+
foreach (var templateName in _provider.GetTemplateNames())
47+
{
48+
if (list.Any(e => e.Name == templateName))
49+
{
50+
continue;
51+
}
52+
53+
var handler = _provider.CreateTemplateFileHandler(templateName);
54+
list.Add(new Template(templateName, handler));
55+
}
56+
57+
return list;
58+
});
59+
60+
public IEnumerable<Template> GetTemplates() => LazyList.Value;
61+
}
62+
}

0 commit comments

Comments
 (0)