6
6
using System . Collections . Generic ;
7
7
using System . Collections . ObjectModel ;
8
8
using Rubberduck . Navigation . CodeExplorer ;
9
- using System . Windows ;
10
- using Rubberduck . Navigation . Folders ;
9
+ using Rubberduck . Parsing . UIContext ;
11
10
using Rubberduck . VBEditor . SafeComWrappers . Abstract ;
12
11
13
12
namespace Rubberduck . CodeAnalysis . CodeMetrics
14
13
{
15
- public class CodeMetricsViewModel : ViewModelBase , IDisposable
14
+ public sealed class CodeMetricsViewModel : ViewModelBase , IDisposable
16
15
{
17
16
private readonly RubberduckParserState _state ;
18
17
private readonly ICodeMetricsAnalyst _analyst ;
19
- //private readonly FolderHelper _folderHelper;
20
18
private readonly IVBE _vbe ;
19
+ private readonly IUiDispatcher _uiDispatcher ;
21
20
22
21
public CodeMetricsViewModel (
23
22
RubberduckParserState state ,
24
23
ICodeMetricsAnalyst analyst ,
25
- //FolderHelper folderHelper,
26
- IVBE vbe )
24
+ IVBE vbe ,
25
+ IUiDispatcher uiDispatcher )
27
26
{
28
27
_state = state ;
29
- _analyst = analyst ;
30
- //_folderHelper = folderHelper;
31
28
_state . StateChanged += OnStateChanged ;
29
+
30
+ _analyst = analyst ;
32
31
_vbe = vbe ;
33
- }
34
-
35
- private void OnStateChanged ( object sender , ParserStateEventArgs e )
36
- {
37
- if ( e . State != ParserState . Ready && e . State != ParserState . Error && e . State != ParserState . ResolverError && e . State != ParserState . UnexpectedError )
38
- {
39
- IsBusy = true ;
40
- }
32
+ _uiDispatcher = uiDispatcher ;
41
33
42
- if ( e . State == ParserState . Ready )
43
- {
44
- UpdateData ( ) ;
45
- IsBusy = false ;
46
- }
34
+ OnPropertyChanged ( nameof ( Projects ) ) ;
35
+ }
47
36
48
- if ( e . State == ParserState . Error || e . State == ParserState . ResolverError || e . State == ParserState . UnexpectedError )
37
+ private bool _unparsed = true ;
38
+ public bool Unparsed
39
+ {
40
+ get => _unparsed ;
41
+ set
49
42
{
50
- IsBusy = false ;
43
+ if ( _unparsed == value )
44
+ {
45
+ return ;
46
+ }
47
+ _unparsed = value ;
48
+ OnPropertyChanged ( ) ;
51
49
}
52
50
}
53
51
54
- private void UpdateData ( )
52
+ private void OnStateChanged ( object sender , ParserStateEventArgs e )
55
53
{
56
- IsBusy = true ;
57
-
58
- var metricResults = _analyst . GetMetrics ( _state ) ;
59
- resultsByDeclaration = metricResults . GroupBy ( r => r . Declaration ) . ToDictionary ( g => g . Key , g => g . ToList ( ) ) ;
54
+ Unparsed = false ;
55
+ IsBusy = _state . Status != ParserState . Pending && _state . Status <= ParserState . ResolvedDeclarations ;
60
56
61
- if ( Projects == null )
57
+ if ( e . State != ParserState . ResolvedDeclarations )
62
58
{
63
- Projects = new ObservableCollection < CodeExplorerItemViewModel > ( ) ;
59
+ return ;
64
60
}
65
61
66
- IsBusy = _state . Status != ParserState . Pending && _state . Status <= ParserState . ResolvedDeclarations ;
67
-
68
- var userDeclarations = _state . DeclarationFinder . AllUserDeclarations
69
- . GroupBy ( declaration => declaration . ProjectId )
70
- . ToList ( ) ;
71
-
72
- //var newProjects = userDeclarations
73
- // .Where(grouping => grouping.Any(declaration => declaration.DeclarationType == DeclarationType.Project))
74
- // .Select(grouping =>
75
- // new CodeExplorerProjectViewModel(_folderHelper,
76
- // grouping.SingleOrDefault(declaration => declaration.DeclarationType == DeclarationType.Project),
77
- // grouping,
78
- // _vbe)).ToList();
79
-
80
- //UpdateNodes(Projects, newProjects);
81
-
82
- //Projects = new ObservableCollection<CodeExplorerItemViewModel>(newProjects);
83
-
84
- IsBusy = false ;
62
+ Synchronize ( _state . DeclarationFinder . AllUserDeclarations . ToList ( ) ) ;
85
63
}
86
64
87
- private void UpdateNodes ( IEnumerable < CodeExplorerItemViewModel > oldList , IEnumerable < CodeExplorerItemViewModel > newList )
65
+ private void Synchronize ( List < Declaration > declarations )
88
66
{
89
- foreach ( var item in newList )
67
+ var metricResults = _analyst . GetMetrics ( _state ) ;
68
+ _resultsByDeclaration = metricResults . GroupBy ( r => r . Declaration ) . ToDictionary ( g => g . Key , g => g . ToList ( ) ) ;
69
+
70
+ _uiDispatcher . Invoke ( ( ) =>
90
71
{
91
- CodeExplorerItemViewModel oldItem ;
72
+ var existing = Projects . OfType < CodeExplorerProjectViewModel > ( ) . ToList ( ) ;
92
73
93
- if ( item is CodeExplorerCustomFolderViewModel )
94
- {
95
- oldItem = oldList . FirstOrDefault ( i => i . Name == item . Name ) ;
96
- }
97
- else
74
+ foreach ( var project in existing )
98
75
{
99
- oldItem = oldList . FirstOrDefault ( i =>
100
- item . QualifiedSelection != null && i . QualifiedSelection != null &&
101
- i . QualifiedSelection . Value . QualifiedName . ProjectId ==
102
- item . QualifiedSelection . Value . QualifiedName . ProjectId &&
103
- i . QualifiedSelection . Value . QualifiedName . ComponentName ==
104
- item . QualifiedSelection . Value . QualifiedName . ComponentName &&
105
- i . QualifiedSelection . Value . Selection == item . QualifiedSelection . Value . Selection ) ;
76
+ project . Synchronize ( declarations ) ;
77
+ if ( project . Declaration is null )
78
+ {
79
+ Projects . Remove ( project ) ;
80
+ }
106
81
}
107
82
108
- //if (oldItem != null)
109
- //{
110
- // item.IsExpanded = oldItem.IsExpanded;
111
- // item.IsSelected = oldItem.IsSelected;
112
-
113
- // if (oldItem.Items.Any() && item.Items.Any())
114
- // {
115
- // UpdateNodes(oldItem.Items, item.Items);
116
- // }
117
- //}
118
- }
119
- }
120
-
121
- public void Dispose ( )
122
- {
123
- Dispose ( true ) ;
124
- GC . SuppressFinalize ( this ) ;
125
- }
126
-
127
- private bool _isDisposed ;
128
- protected virtual void Dispose ( bool disposing )
129
- {
130
- if ( _isDisposed || ! disposing )
131
- {
132
- return ;
133
- }
134
- _isDisposed = true ;
83
+ var adding = declarations . OfType < ProjectDeclaration > ( ) . ToList ( ) ;
135
84
136
- _state . StateChanged -= OnStateChanged ;
85
+ foreach ( var project in adding )
86
+ {
87
+ var model = new CodeExplorerProjectViewModel ( project , declarations , _state , _vbe , false ) ;
88
+ Projects . Add ( model ) ;
89
+ model . IsExpanded = true ;
90
+ }
91
+ } ) ;
137
92
}
138
93
139
- private Dictionary < Declaration , List < ICodeMetricResult > > resultsByDeclaration ;
140
-
141
- private CodeExplorerItemViewModel _selectedItem ;
142
- public CodeExplorerItemViewModel SelectedItem
94
+ private ICodeExplorerNode _selectedItem ;
95
+ public ICodeExplorerNode SelectedItem
143
96
{
144
97
get => _selectedItem ;
145
98
set
@@ -154,26 +107,14 @@ public CodeExplorerItemViewModel SelectedItem
154
107
}
155
108
}
156
109
157
- private ObservableCollection < CodeExplorerItemViewModel > _projects ;
158
- public ObservableCollection < CodeExplorerItemViewModel > Projects
159
- {
160
- get => _projects ;
161
- set
162
- {
163
- _projects = new ObservableCollection < CodeExplorerItemViewModel > ( value . OrderBy ( o => o . NameWithSignature ) ) ;
164
-
165
- OnPropertyChanged ( ) ;
166
- OnPropertyChanged ( nameof ( TreeViewVisibility ) ) ;
167
- }
168
- }
110
+ public ObservableCollection < ICodeExplorerNode > Projects { get ; } = new ObservableCollection < ICodeExplorerNode > ( ) ;
169
111
170
- public Visibility TreeViewVisibility => Projects == null || Projects . Count == 0 ? Visibility . Collapsed : Visibility . Visible ;
171
-
112
+ private Dictionary < Declaration , List < ICodeMetricResult > > _resultsByDeclaration ;
172
113
public ObservableCollection < ICodeMetricResult > Metrics
173
114
{
174
115
get
175
116
{
176
- var results = resultsByDeclaration ? . FirstOrDefault ( f => ReferenceEquals ( f . Key , SelectedItem . Declaration ) ) ;
117
+ var results = _resultsByDeclaration ? . FirstOrDefault ( f => ReferenceEquals ( f . Key , SelectedItem . Declaration ) ) ;
177
118
return results ? . Value == null ? new ObservableCollection < ICodeMetricResult > ( ) : new ObservableCollection < ICodeMetricResult > ( results . Value . Value ) ;
178
119
}
179
120
}
@@ -185,23 +126,27 @@ public bool IsBusy
185
126
set
186
127
{
187
128
_isBusy = value ;
188
- EmptyUIRefreshMessageVisibility = false ;
189
129
OnPropertyChanged ( ) ;
190
130
}
191
131
}
192
132
193
- private bool _emptyUIRefreshMessageVisibility = true ;
194
- public bool EmptyUIRefreshMessageVisibility
133
+ public void Dispose ( )
195
134
{
196
- get => _emptyUIRefreshMessageVisibility ;
197
- set
135
+ Dispose ( true ) ;
136
+ GC . SuppressFinalize ( this ) ;
137
+ }
138
+
139
+ private bool _isDisposed ;
140
+
141
+ private void Dispose ( bool disposing )
142
+ {
143
+ if ( _isDisposed || ! disposing )
198
144
{
199
- if ( _emptyUIRefreshMessageVisibility != value )
200
- {
201
- _emptyUIRefreshMessageVisibility = value ;
202
- OnPropertyChanged ( ) ;
203
- }
145
+ return ;
204
146
}
147
+ _isDisposed = true ;
148
+
149
+ _state . StateChanged -= OnStateChanged ;
205
150
}
206
151
}
207
152
}
0 commit comments