1
1
using System ;
2
+ using System . Collections . Generic ;
2
3
using System . ComponentModel ;
3
4
using System . Drawing ;
4
5
using System . Linq ;
5
6
using System . Runtime . CompilerServices ;
7
+ using System . Threading ;
8
+ using System . Threading . Tasks ;
6
9
using System . Windows . Forms ;
7
10
using Analogy . CommonControls . Properties ;
11
+ using DevExpress . Office . Utils ;
8
12
using Newtonsoft . Json ;
9
13
using Newtonsoft . Json . Linq ;
10
14
@@ -21,17 +25,19 @@ public class JsonTreeView : TreeView
21
25
private ToolStripMenuItem expandAllMenuItem ;
22
26
private StatusStrip statusStrip1 ;
23
27
private string previouslySelectedNodeText ;
28
+ private CancellationTokenSource cancellationTokenSource ;
24
29
public event EventHandler < string > OnNodeChanged ;
25
30
public string Message { get ; set ; }
26
31
public JsonTreeView ( )
27
32
{
28
33
InitializeComponent ( ) ;
34
+ cancellationTokenSource = new CancellationTokenSource ( ) ;
29
35
AfterSelect += this_AfterSelect ;
30
36
DoubleClick += ( s , e ) =>
31
37
{
32
38
if ( SelectedNode != null )
33
39
{
34
- Clipboard . SetText ( SelectedNode . Text , TextDataFormat . UnicodeText ) ;
40
+ Clipboard . SetText ( SelectedNode . Text , TextDataFormat . UnicodeText ) ;
35
41
}
36
42
} ;
37
43
MouseDown += this_MouseDown ;
@@ -113,21 +119,25 @@ private void LoadImageList()
113
119
}
114
120
115
121
[ DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ]
116
- private void LoadTree ( object jsonData )
122
+ private List < TreeNode > LoadTree ( object jsonData , CancellationToken cancellationToken )
117
123
{
118
- Nodes . Clear ( ) ;
124
+ if ( cancellationToken . IsCancellationRequested )
125
+ {
126
+ return new ( ) ;
127
+ }
128
+ List < TreeNode > nodes = new ( ) ;
119
129
if ( jsonData is JArray jsonArray )
120
130
{
121
131
var rootNode = new JsonTreeNode ( JsonNodeType . Object , "(root array)" ) ;
122
132
foreach ( JToken jToken in jsonArray )
123
133
{
124
134
var node = new JsonTreeNode ( JsonNodeType . Array , jToken . Type . ToString ( ) ) ;
125
135
rootNode . Nodes . Add ( node ) ;
126
- LoadObject ( jToken as JObject , node ) ;
136
+ LoadObject ( jToken as JObject , node , cancellationToken ) ;
127
137
}
128
138
TreeNode [ ] rootNodeArray = new TreeNode [ rootNode . Nodes . Count ] ;
129
139
rootNode . Nodes . CopyTo ( rootNodeArray , 0 ) ;
130
- Nodes . Add ( rootNode ) ;
140
+ nodes . Add ( rootNode ) ;
131
141
SelectedNode = rootNodeArray . First ( ) as JsonTreeNode ;
132
142
rootNode . ImageKey = rootNode . NodeType . ToString ( ) ;
133
143
rootNode . SelectedImageKey = rootNode . ImageKey ;
@@ -137,13 +147,15 @@ private void LoadTree(object jsonData)
137
147
if ( jsonData is JObject json )
138
148
{
139
149
var rootNode = new JsonTreeNode ( JsonNodeType . Object , "(root)" ) ;
140
- Nodes . Add ( rootNode ) ;
150
+ nodes . Add ( rootNode ) ;
141
151
SelectedNode = rootNode ;
142
152
rootNode . ImageKey = rootNode . NodeType . ToString ( ) ;
143
153
rootNode . SelectedImageKey = rootNode . ImageKey ;
144
- LoadObject ( json , rootNode ) ;
154
+ LoadObject ( json , rootNode , cancellationToken ) ;
145
155
rootNode . ExpandAll ( ) ;
146
156
}
157
+
158
+ return nodes ;
147
159
}
148
160
[ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
149
161
private static bool TryParse ( string strInput , out JToken output )
@@ -182,52 +194,66 @@ private static bool TryParse(string strInput, out JToken output)
182
194
return false ;
183
195
}
184
196
}
185
- private void AddNode ( JsonTreeNode parentNode , string property , JToken item )
197
+ private void AddNode ( JsonTreeNode parentNode , string property , JToken item , CancellationToken cancellationToken )
186
198
{
199
+ if ( cancellationToken . IsCancellationRequested )
200
+ {
201
+ return ;
202
+ }
203
+
187
204
var node = JsonTreeNodeCreator . CreateNode ( property , item ) ;
188
205
parentNode . Nodes . Add ( node ) ;
189
206
if ( item . Type == JTokenType . Array )
190
207
{
191
- LoadArray ( item , node ) ;
208
+ LoadArray ( item , node , cancellationToken ) ;
192
209
}
193
210
194
211
else if ( item . Type == JTokenType . Object )
195
212
{
196
- LoadObject ( item as JObject , node ) ;
213
+ LoadObject ( item as JObject , node , cancellationToken ) ;
197
214
}
198
215
else if ( TryParse ( item . ToString ( ) , out var token ) )
199
216
{
200
217
node . Text = property ;
201
218
if ( token . Type == JTokenType . Array )
202
219
{
203
- LoadArray ( token , node ) ;
220
+ LoadArray ( token , node , cancellationToken ) ;
204
221
}
205
222
206
223
else if ( token . Type == JTokenType . Object )
207
224
{
208
- LoadObject ( token as JObject , node ) ;
225
+ LoadObject ( token as JObject , node , cancellationToken ) ;
209
226
}
210
227
}
211
228
}
212
229
213
- private void LoadArray ( JToken value , JsonTreeNode node )
230
+ private void LoadArray ( JToken value , JsonTreeNode node , CancellationToken cancellationToken )
214
231
{
232
+ if ( cancellationToken . IsCancellationRequested )
233
+ {
234
+ return ;
235
+ }
215
236
foreach ( var item in value )
216
237
{
217
- AddNode ( node , null , item ) ;
238
+ AddNode ( node , null , item , cancellationToken ) ;
218
239
}
219
240
}
220
241
221
- private void LoadObject ( JObject obj , JsonTreeNode node )
242
+ private void LoadObject ( JObject obj , JsonTreeNode node , CancellationToken cancellationToken )
222
243
{
244
+ if ( cancellationToken . IsCancellationRequested )
245
+ {
246
+ return ;
247
+ }
248
+
223
249
if ( obj is null )
224
250
{
225
251
return ;
226
252
}
227
253
228
254
foreach ( var item in obj )
229
255
{
230
- AddNode ( node , item . Key , item . Value ) ;
256
+ AddNode ( node , item . Key , item . Value , cancellationToken ) ;
231
257
}
232
258
}
233
259
@@ -280,7 +306,7 @@ private void InitializeComponent()
280
306
get => base . SelectedNode as JsonTreeNode ;
281
307
set => base . SelectedNode = value ;
282
308
}
283
-
309
+
284
310
private void this_AfterSelect ( object sender , TreeViewEventArgs e )
285
311
{
286
312
// restore previous seelcted node text and store the next
@@ -292,9 +318,9 @@ private void this_AfterSelect(object sender, TreeViewEventArgs e)
292
318
previouslySelectedNodeText = e . Node . Text ;
293
319
294
320
e . Node . Text = ( ( JsonTreeNode ) e . Node ) . TextWhenSelected ;
295
- OnNodeChanged ? . Invoke ( this , e . Node . Text ) ;
321
+ OnNodeChanged ? . Invoke ( this , e . Node . Text ) ;
296
322
}
297
-
323
+
298
324
private void this_MouseDown ( object sender , MouseEventArgs e )
299
325
{
300
326
if ( e . Button == MouseButtons . Right )
@@ -330,13 +356,23 @@ public void ClearList()
330
356
{
331
357
Nodes . Clear ( ) ;
332
358
}
333
- public void ShowJson ( string jsonString )
359
+ public async Task ShowJson ( string jsonString )
334
360
{
335
361
Message = jsonString ;
336
362
try
337
363
{
364
+ BeginUpdate ( ) ;
365
+ Nodes . Clear ( ) ;
366
+ cancellationTokenSource ? . Cancel ( ) ;
367
+ cancellationTokenSource = new CancellationTokenSource ( ) ;
368
+ var token = cancellationTokenSource . Token ;
338
369
object json = JsonConvert . DeserializeObject ( jsonString ) ;
339
- LoadTree ( json ) ;
370
+ var nodes = await Task . Run ( ( ) => LoadTree ( json , token ) ) ;
371
+ if ( ! token . IsCancellationRequested )
372
+ {
373
+ Nodes . AddRange ( nodes . ToArray ( ) ) ;
374
+ }
375
+ EndUpdate ( ) ;
340
376
}
341
377
catch ( Exception e )
342
378
{
0 commit comments