Skip to content

Commit b40a96e

Browse files
committed
Add remove references UI implementation.
1 parent 715d8a1 commit b40a96e

30 files changed

+1434
-304
lines changed

Rubberduck.Core/AddRemoveReferences/IReferenceInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ public interface IReferenceInfo
1313
string FullPath { get; }
1414
int Major { get; }
1515
int Minor { get; }
16+
int? Priority { get; }
1617
}
1718
}
Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,89 @@
11
using System;
2+
using System.ComponentModel;
3+
using System.IO;
4+
using System.Runtime.CompilerServices;
25
using System.Runtime.InteropServices.ComTypes;
36
using Rubberduck.VBEditor.SafeComWrappers;
47
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
58

69
namespace Rubberduck.AddRemoveReferences
710
{
8-
public class ReferenceModel
11+
public class ReferenceModel : INotifyPropertyChanged
912
{
13+
public event PropertyChangedEventHandler PropertyChanged;
14+
1015
public ReferenceModel(IVBProject project, int priority)
1116
{
12-
Name = project.Name;
17+
Name = project.Name ?? string.Empty;
1318
Priority = priority;
1419
Guid = Guid.Empty;
15-
Description = project.Description;
16-
Version = default(Version);
17-
FullPath = project.FileName;
20+
Description = project.Description ?? string.Empty;
21+
FullPath = project.FileName ?? string.Empty;
1822
IsBuiltIn = false;
1923
Type = ReferenceKind.Project;
2024
}
2125

2226
public ReferenceModel(RegisteredLibraryInfo info)
2327
{
24-
Name = info.Name;
28+
Name = info.Name ?? string.Empty;
2529
Guid = info.Guid;
26-
Description = info.Description;
30+
Description = string.IsNullOrEmpty(info.Description) ? Path.GetFileNameWithoutExtension(info.FullPath) : info.Description;
2731
Major = info.Major;
2832
Minor = info.Minor;
2933
FullPath = info.FullPath;
34+
LocaleName = info.LocaleName;
3035
IsBuiltIn = false;
3136
Type = ReferenceKind.TypeLibrary;
3237
Flags = info.Flags;
38+
IsRegistered = true;
39+
}
40+
41+
public ReferenceModel(RegisteredLibraryInfo info, IReference reference, int priority) : this(info)
42+
{
43+
Priority = priority;
44+
IsBuiltIn = reference.IsBuiltIn;
45+
IsBroken = reference.IsBroken;
46+
IsReferenced = true;
3347
}
3448

3549
public ReferenceModel(IReference reference, int priority)
3650
{
37-
IsSelected = true;
3851
Priority = priority;
3952
Name = reference.Name;
4053
Guid = new Guid(reference.Guid);
41-
Description = reference.Description;
42-
Version = new Version(reference.Major, reference.Minor);
54+
Description = string.IsNullOrEmpty(reference.Description) ? Path.GetFileNameWithoutExtension(reference.FullPath) : reference.Description;
55+
Major = reference.Major;
56+
Minor = reference.Minor;
4357
FullPath = reference.FullPath;
4458
IsBuiltIn = reference.IsBuiltIn;
4559
IsBroken = reference.IsBroken;
60+
IsReferenced = true;
4661
Type = reference.Type;
4762
}
4863

49-
public bool IsSelected { get; set; }
50-
public bool IsRemoved { get; set; }
51-
public int Priority { get; set; }
64+
private bool _pinned;
65+
public bool IsPinned
66+
{
67+
get => _pinned;
68+
set
69+
{
70+
_pinned = value;
71+
NotifyPropertyChanged();
72+
}
73+
}
5274

75+
public bool IsRecent { get; set; }
76+
77+
public bool IsRegistered { get; set; }
78+
public bool IsReferenced { get; set; }
79+
public int? Priority { get; set; }
80+
5381
public string Name { get; }
5482
public Guid Guid { get; }
5583
public string Description { get; }
56-
public Version Version { get; }
5784
public string FullPath { get; }
85+
public string LocaleName { get; }
86+
5887
public bool IsBuiltIn { get; }
5988
public bool IsBroken { get; }
6089
public LIBFLAGS Flags { get; }
@@ -64,17 +93,35 @@ public ReferenceModel(IReference reference, int priority)
6493
private string FullPath64 { get; }
6594
public int Major { get; set; }
6695
public int Minor { get; set; }
96+
public string Version => $"{Major}.{Minor}";
97+
98+
public ReferenceStatus Status
99+
{
100+
get
101+
{
102+
var status = IsPinned ? ReferenceStatus.Pinned : ReferenceStatus.None;
103+
if (!Priority.HasValue)
104+
{
105+
return IsRecent ? status | ReferenceStatus.Recent : status;
106+
}
67107

68-
public ReferenceStatus Status => IsBuiltIn
69-
? ReferenceStatus.BuiltIn
70-
: IsBroken
71-
? ReferenceStatus.Broken
72-
: IsRemoved
73-
? ReferenceStatus.Removed
74-
: IsSelected
75-
? ReferenceStatus.Loaded
76-
: ReferenceStatus.None;
108+
if (IsBroken)
109+
{
110+
return status | ReferenceStatus.Broken;
111+
}
77112

113+
if (IsBuiltIn)
114+
{
115+
return status | ReferenceStatus.BuiltIn;
116+
}
78117

118+
return status | (IsReferenced ? ReferenceStatus.Loaded : ReferenceStatus.Added);
119+
}
120+
}
121+
122+
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
123+
{
124+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
125+
}
79126
}
80127
}
Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
using System;
2+
13
namespace Rubberduck.AddRemoveReferences
24
{
5+
[Flags]
36
public enum ReferenceStatus
47
{
5-
None,
6-
BuiltIn,
7-
Loaded,
8-
Broken,
9-
Removed,
8+
None = 0,
9+
BuiltIn = 1 << 1,
10+
Loaded = 1 << 2,
11+
Broken = 1 << 3,
12+
Pinned = 1 << 4,
13+
Recent = 1 << 5,
14+
Added = 1 << 6
1015
}
1116
}

Rubberduck.Core/AddRemoveReferences/RegisteredLibraryFinderService.cs

Lines changed: 23 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3-
using System.Diagnostics;
4-
using System.Globalization;
5-
using System.IO;
3+
using System.Linq;
64
using System.Runtime.InteropServices.ComTypes;
75
using Microsoft.Win32;
86

@@ -19,22 +17,15 @@ public static string GetKeyName(this RegistryKey key)
1917

2018
public interface IRegisteredLibraryFinderService
2119
{
22-
IEnumerable<ReferenceModel> FindRegisteredLibraries();
20+
IEnumerable<RegisteredLibraryInfo> FindRegisteredLibraries();
2321
}
2422

23+
// inspired from https://github.com/rossknudsen/Kavod.ComReflection
2524
public class RegisteredLibraryFinderService : IRegisteredLibraryFinderService
2625
{
27-
private readonly bool _use64BitPaths;
28-
29-
// inspired from https://github.com/rossknudsen/Kavod.ComReflection
30-
public RegisteredLibraryFinderService(bool use64BitPaths)
31-
{
32-
_use64BitPaths = use64BitPaths;
33-
}
34-
3526
private static readonly List<string> IgnoredKeys = new List<string> { "FLAGS", "HELPDIR" };
3627

37-
public IEnumerable<ReferenceModel> FindRegisteredLibraries()
28+
public IEnumerable<RegisteredLibraryInfo> FindRegisteredLibraries()
3829
{
3930
using (var typelibSubKey = Registry.ClassesRoot.OpenSubKey("TypeLib"))
4031
{
@@ -61,47 +52,37 @@ public IEnumerable<ReferenceModel> FindRegisteredLibraries()
6152
}
6253
}
6354

64-
foreach (var lcid in EnumerateSubKeys(versionKey))
55+
foreach (var lcid in versionKey.GetSubKeyNames().Where(key => !IgnoredKeys.Contains(key)))
6556
{
66-
if (IgnoredKeys.Contains(lcid.GetValue(string.Empty)?.ToString()))
57+
if (!int.TryParse(lcid, out var id))
6758
{
6859
continue;
6960
}
70-
71-
string bit32;
72-
string bit64;
73-
using (var win32 = lcid.OpenSubKey("win32"))
74-
{
75-
bit32 = win32?.GetValue(string.Empty)?.ToString() ?? string.Empty;
76-
}
77-
using (var win64 = lcid.OpenSubKey("win64"))
78-
{
79-
bit64 = win64?.GetValue(string.Empty)?.ToString() ?? string.Empty;
80-
}
81-
var info = new RegisteredLibraryInfo(guid, name, version, bit32, bit64)
61+
using (var paths = versionKey.OpenSubKey(lcid))
8262
{
83-
Flags = flagValue,
84-
};
63+
string bit32;
64+
string bit64;
65+
using (var win32 = paths?.OpenSubKey("win32"))
66+
{
67+
bit32 = win32?.GetValue(string.Empty)?.ToString() ?? string.Empty;
68+
}
69+
using (var win64 = paths?.OpenSubKey("win64"))
70+
{
71+
bit64 = win64?.GetValue(string.Empty)?.ToString() ?? string.Empty;
72+
}
8573

86-
yield return new ReferenceModel(info);
74+
yield return new RegisteredLibraryInfo(guid, name, version, bit32, bit64)
75+
{
76+
Flags = flagValue,
77+
LocaleId = id
78+
};
79+
}
8780
}
8881
}
8982
}
9083
}
9184
}
9285

93-
//private static readonly HashSet<string> Extensions = new HashSet<string> { "tlb", "olb", "dll" };
94-
95-
//private string GetLibraryExtension(string fullPath)
96-
//{
97-
// var lastBackslashIndex = fullPath.LastIndexOf(@"\", StringComparison.OrdinalIgnoreCase);
98-
// var lastDotIndex = fullPath.LastIndexOf(".", StringComparison.OrdinalIgnoreCase);
99-
// var result = lastBackslashIndex > lastDotIndex
100-
// ? fullPath.Substring(lastDotIndex + 1, lastBackslashIndex - lastDotIndex)
101-
// : fullPath.Substring(lastDotIndex + 1);
102-
// return result;
103-
//}
104-
10586
private IEnumerable<RegistryKey> EnumerateSubKeys(RegistryKey key)
10687
{
10788
foreach (var keyName in key.GetSubKeyNames())
Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,75 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Globalization;
34
using System.IO;
45
using System.Runtime.InteropServices.ComTypes;
56

67
namespace Rubberduck.AddRemoveReferences
78
{
9+
public struct RegisteredLibraryKey
10+
{
11+
public Guid Guid { get; }
12+
public int Major { get; }
13+
public int Minor { get; }
14+
15+
public RegisteredLibraryKey(Guid guid, int major, int minor)
16+
{
17+
Guid = guid;
18+
Major = major;
19+
Minor = minor;
20+
}
21+
}
22+
823
public class RegisteredLibraryInfo : IReferenceInfo
924
{
25+
private static readonly Dictionary<int, string> NativeLocaleNames = new Dictionary<int, string>
26+
{
27+
{ 0, "Standard" }
28+
};
29+
30+
public RegisteredLibraryKey UniqueId { get; }
1031
public string Name { get; set; }
1132
public Guid Guid { get; set; }
1233
public string Description { get; set; }
1334
public string Version => $"{Major}.{Minor}";
1435
public string FullPath => string.IsNullOrEmpty(FullPath32) || Has64BitVersion && Environment.Is64BitProcess ? FullPath64 : FullPath32;
1536
public int Major { get; set; }
1637
public int Minor { get; set; }
38+
public int LocaleId { get; set; }
39+
40+
public string LocaleName
41+
{
42+
get
43+
{
44+
if (NativeLocaleNames.ContainsKey(LocaleId))
45+
{
46+
return NativeLocaleNames[LocaleId];
47+
}
48+
49+
try
50+
{
51+
var name = CultureInfo.GetCultureInfo(LocaleId).NativeName;
52+
NativeLocaleNames.Add(LocaleId, name);
53+
return name;
54+
}
55+
catch
56+
{
57+
NativeLocaleNames.Add(LocaleId, "Standard");
58+
return "Standard";
59+
}
60+
}
61+
}
62+
1763
public LIBFLAGS Flags { get; set; }
1864

1965
private string FullPath32 { get; }
2066
private string FullPath64 { get; }
2167
public bool Has32BitVersion => !string.IsNullOrEmpty(FullPath32);
2268
public bool Has64BitVersion => !string.IsNullOrEmpty(FullPath64);
2369

24-
public RegisteredLibraryInfo(Guid guid, string name, string version, string path32, string path64)
70+
public int? Priority => null;
71+
72+
public RegisteredLibraryInfo(Guid guid, string description, string version, string path32, string path64)
2573
{
2674
Guid = guid;
2775

@@ -32,12 +80,13 @@ public RegisteredLibraryInfo(Guid guid, string name, string version, string path
3280
Minor = int.TryParse(majorMinor[1], NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var minor) ? minor : 0;
3381
}
3482

35-
FullPath32 = path32;
36-
FullPath64 = path64;
83+
FullPath32 = path32 ?? string.Empty;
84+
FullPath64 = path64 ?? string.Empty;
3785

38-
Name = !string.IsNullOrEmpty(name) ? name : Path.GetFileNameWithoutExtension(FullPath);
86+
Description = !string.IsNullOrEmpty(description) ? description : Path.GetFileNameWithoutExtension(FullPath);
87+
UniqueId = new RegisteredLibraryKey(guid, Major, Minor);
3988
}
4089

41-
public override string ToString() => Name;
90+
public override string ToString() => Description;
4291
}
4392
}

0 commit comments

Comments
 (0)