Skip to content

Commit 4e2c8a1

Browse files
committed
Reimplemented clipboard functionality.
1 parent d97972b commit 4e2c8a1

File tree

6 files changed

+172
-147
lines changed

6 files changed

+172
-147
lines changed

DataExchange/ReClassClipboard.cs

Lines changed: 30 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
using System.Collections.Generic;
1+
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics.Contracts;
3-
using System.Linq;
4+
using System.IO;
45
using System.Windows.Forms;
56
using ReClassNET.Logger;
67
using ReClassNET.Nodes;
@@ -9,146 +10,56 @@ namespace ReClassNET.DataExchange
910
{
1011
public class ReClassClipboard
1112
{
12-
private const string FormatClasses = "ReClass.NET::Classes";
13-
private const string FormatNodes = "ReClass.NET::Nodes";
13+
/// <summary>The clipboard format string.</summary>
14+
private const string ClipboardFormat = "ReClass.NET::Nodes";
1415

15-
public enum Format
16-
{
17-
Classes,
18-
Nodes
19-
}
20-
21-
public static bool ContainsData(Format format) => Clipboard.ContainsData(format == Format.Classes ? FormatClasses : FormatNodes);
22-
23-
public static void CopyClasses(IEnumerable<ClassNode> classesToCopy, IEnumerable<ClassNode> globalClasses, ILogger logger)
24-
{
25-
Contract.Requires(classesToCopy != null);
26-
Contract.Requires(globalClasses != null);
27-
Contract.Requires(logger != null);
28-
29-
if (!classesToCopy.Any())
30-
{
31-
return;
32-
}
33-
34-
/*var schema = SchemaBuilder.FromClasses(classesToCopy, logger);
35-
36-
Clipboard.Clear();
37-
Clipboard.SetData(FormatClasses, schema.BuildSchema());*/
38-
}
39-
40-
public static List<ClassNode> PasteClasses(IEnumerable<ClassNode> globalClasses, ILogger logger)
41-
{
42-
Contract.Requires(globalClasses != null);
43-
Contract.Requires(logger != null);
44-
45-
var nodes = new List<ClassNode>();
46-
47-
if (ContainsData(Format.Classes))
48-
{
49-
/*var schemaClassNodes = Clipboard.GetData(FormatNodes) as List<SchemaClassNode>;
50-
if (schemaClassNodes != null)
51-
{
52-
foreach (var schemaClass in schemaClassNodes)
53-
{
54-
// Rename classes which already exist.
55-
var name = schemaClass.Name;
56-
for (var i = 1; globalClasses.Any(c => c.Name == schemaClass.Name); ++i)
57-
{
58-
schemaClass.Name = $"{name}_{i}";
59-
}
16+
/// <summary>Checks if ReClass.NET nodes are present in the clipboard.</summary>
17+
public static bool ContainsNodes => Clipboard.ContainsData(ClipboardFormat);
6018

61-
// Remove all reference types with unknown references.
62-
schemaClass.Nodes.RemoveAll(n => n is SchemaReferenceNode && !globalClasses.Any(c => c.Name == ((SchemaReferenceNode)n).InnerNode?.Name));
63-
}
64-
65-
// Now remove all reference types with unknown references.
66-
67-
//schemaClassNodes.RemoveAll(n => n is SchemaReferenceNode && !globalClasses.Any(c => c.Name == ((SchemaReferenceNode)n).InnerNode?.Name));
68-
69-
var classMap = schemaClassNodes.OfType<SchemaReferenceNode>().ToDictionary(
70-
srn => srn.InnerNode,
71-
srn => classes.First(c => c.Name == srn.InnerNode.Name)
72-
);
73-
74-
foreach (var schemaNode in schemaClassNodes)
75-
{
76-
BaseNode node;
77-
if (SchemaBuilder.TryCreateNodeFromSchema(schemaNode, parentNode, classMap, logger, out node))
78-
{
79-
nodes.Add(node);
80-
}
81-
}
82-
}*/
83-
}
84-
85-
return nodes;
86-
}
87-
88-
public static void CopyNodes(IEnumerable<BaseNode> nodes, IEnumerable<ClassNode> globalClasses, ILogger logger)
19+
/// <summary>Copies the nodes to the clipboard.</summary>
20+
/// <param name="nodes">The nodes to copy.</param>
21+
/// <param name="logger">The logger.</param>
22+
public static void Copy(IEnumerable<BaseNode> nodes, ILogger logger)
8923
{
9024
Contract.Requires(nodes != null);
91-
Contract.Requires(globalClasses != null);
9225
Contract.Requires(logger != null);
9326

94-
if (!nodes.Any())
27+
using (var ms = new MemoryStream())
9528
{
96-
return;
97-
}
98-
99-
/*var classMap = globalClasses.ToDictionary(
100-
c => c,
101-
c => new SchemaClassNode { Name = c.Name }
102-
);
29+
ReClassNetFile.WriteNodes(ms, nodes, logger);
10330

104-
var schemaNodes = new List<SchemaNode>();
105-
foreach (var node in nodes)
106-
{
107-
SchemaNode schemaNode;
108-
if (SchemaBuilder.TryCreateSchemaFromNode(node, classMap, logger, out schemaNode))
109-
{
110-
schemaNodes.Add(schemaNode);
111-
}
31+
Clipboard.SetData(ClipboardFormat, ms.ToArray());
11232
}
113-
114-
Clipboard.Clear();
115-
Clipboard.SetData(FormatNodes, schemaNodes);*/
11633
}
11734

118-
public static List<BaseNode> PasteNodes(ClassNode parentNode, IEnumerable<ClassNode> globalClasses, ILogger logger)
35+
/// <summary>Pastes nodes from the clipboard.</summary>
36+
/// <param name="templateProject">The project to resolve class references.</param>
37+
/// <param name="logger">The logger.</param>
38+
/// <returns>A list of <see cref="ClassNode"/> and <see cref="BaseNode"/>. If no data was present, both lists are empty.</returns>
39+
public static Tuple<List<ClassNode>, List<BaseNode>> Paste(ReClassNetProject templateProject, ILogger logger)
11940
{
120-
Contract.Requires(parentNode != null);
121-
Contract.Requires(globalClasses != null);
41+
Contract.Requires(templateProject != null);
12242
Contract.Requires(logger != null);
12343
Contract.Ensures(Contract.Result<List<BaseNode>>() != null);
12444

45+
var classes = new List<ClassNode>();
12546
var nodes = new List<BaseNode>();
12647

127-
if (ContainsData(Format.Nodes))
48+
if (ContainsNodes)
12849
{
129-
/*var schemaNodes = Clipboard.GetData(FormatNodes) as List<SchemaNode>;
130-
if (schemaNodes != null)
50+
var data = Clipboard.GetData(ClipboardFormat) as byte[];
51+
if (data != null)
13152
{
132-
// Now remove all reference types with unknown references.
133-
schemaNodes.RemoveAll(n => n is SchemaReferenceNode && !globalClasses.Any(c => c.Name == ((SchemaReferenceNode)n).InnerNode?.Name));
134-
135-
var classMap = schemaNodes.OfType<SchemaReferenceNode>().ToDictionary(
136-
srn => srn.InnerNode,
137-
srn => globalClasses.First(c => c.Name == srn.InnerNode.Name)
138-
);
139-
140-
foreach (var schemaNode in schemaNodes)
53+
using (var ms = new MemoryStream(data))
14154
{
142-
BaseNode node;
143-
if (SchemaBuilder.TryCreateNodeFromSchema(schemaNode, parentNode, classMap, logger, out node))
144-
{
145-
nodes.Add(node);
146-
}
55+
var result = ReClassNetFile.ReadNodes(ms, templateProject, logger);
56+
classes.AddRange(result.Item1);
57+
nodes.AddRange(result.Item2);
14758
}
148-
}*/
59+
}
14960
}
15061

151-
return nodes;
62+
return Tuple.Create(classes, nodes);
15263
}
15364
}
15465
}

DataExchange/ReClassNetFile.Read.cs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,12 @@ public void Load(Stream input, ILogger logger)
5656
AddressFormula = element.Attribute(XmlAddressAttribute)?.Value ?? string.Empty
5757
};
5858

59-
project.AddClass(node);
59+
if (!project.ContainsClass(node.Uuid))
60+
{
61+
project.AddClass(node);
6062

61-
classes.Add(Tuple.Create(element, node));
63+
classes.Add(Tuple.Create(element, node));
64+
}
6265
}
6366

6467
foreach (var t in classes)
@@ -184,27 +187,46 @@ private static void TryGetAttributeValue(XElement element, string attribute, out
184187
}
185188
}
186189

187-
public static List<BaseNode> ReadNodeElements(Stream input, ReClassNetProject project, ILogger logger)
190+
public static Tuple<List<ClassNode>, List<BaseNode>> ReadNodes(Stream input, ReClassNetProject templateProject, ILogger logger)
188191
{
189192
Contract.Requires(input != null);
190193
Contract.Requires(logger != null);
191194

192-
project = project ?? new ReClassNetProject();
195+
using (var project = new ReClassNetProject())
196+
{
197+
if (templateProject != null)
198+
{
199+
templateProject.Classes.ForEach(project.AddClass);
200+
}
193201

194-
var file = new ReClassNetFile(project);
195-
file.Load(input, logger);
202+
var file = new ReClassNetFile(project);
203+
file.Load(input, logger);
196204

197-
var nodes = new List<BaseNode>();
205+
var classes = new List<ClassNode>();
198206

199-
var classNode = project.Classes.FirstOrDefault(c => c.Name == SerialisationClassName);
200-
if (classNode != null)
201-
{
202-
nodes.AddRange(classNode.Nodes);
207+
var nodes = new List<BaseNode>();
203208

204-
project.Remove(classNode);
205-
}
209+
var serialisationClassNode = project.Classes.FirstOrDefault(c => c.Name == SerialisationClassName);
210+
if (serialisationClassNode != null)
211+
{
212+
if (templateProject != null)
213+
{
214+
foreach (var classNode in project.Classes.Where(c => c != serialisationClassNode))
215+
{
216+
if (!templateProject.ContainsClass(classNode.Uuid))
217+
{
218+
classes.Add(classNode);
219+
}
220+
}
221+
}
222+
223+
nodes.AddRange(serialisationClassNode.Nodes);
206224

207-
return nodes;
225+
project.Remove(serialisationClassNode);
226+
}
227+
228+
return Tuple.Create(classes, nodes);
229+
}
208230
}
209231
}
210232
}

DataExchange/ReClassNetFile.Write.cs

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,53 @@ public static void WriteNodes(Stream output, IEnumerable<BaseNode> nodes, ILogge
131131
Contract.Requires(nodes != null);
132132
Contract.Requires(logger != null);
133133

134-
var project = new ReClassNetProject();
135-
136-
var tempClass = new ClassNode(false)
134+
using (var project = new ReClassNetProject())
137135
{
138-
Name = SerialisationClassName
139-
};
136+
Action<BaseReferenceNode> recursiveAddReferences = null;
137+
recursiveAddReferences = delegate (BaseReferenceNode referenceNode)
138+
{
139+
if (project.ContainsClass(referenceNode.InnerNode.Uuid))
140+
{
141+
return;
142+
}
140143

141-
nodes.Select(n => n.Clone()).ForEach(tempClass.AddNode);
144+
project.AddClass(referenceNode.InnerNode);
142145

143-
var file = new ReClassNetFile(project);
144-
file.Save(output, logger);
146+
foreach (var reference in referenceNode.InnerNode.Nodes.OfType<BaseReferenceNode>())
147+
{
148+
recursiveAddReferences(reference);
149+
}
150+
};
151+
152+
var serialisationClass = new ClassNode(false)
153+
{
154+
Name = SerialisationClassName
155+
};
156+
157+
project.AddClass(serialisationClass);
158+
159+
foreach (var node in nodes)
160+
{
161+
var classNode = node as ClassNode;
162+
if (classNode != null)
163+
{
164+
project.AddClass(classNode);
165+
166+
continue;
167+
}
168+
169+
var referenceNode = node as BaseReferenceNode;
170+
if (referenceNode != null)
171+
{
172+
recursiveAddReferences(referenceNode);
173+
}
174+
175+
serialisationClass.AddNode(node);
176+
}
177+
178+
var file = new ReClassNetFile(project);
179+
file.Save(output, logger);
180+
}
145181
}
146182
}
147183
}

ReClassNetProject.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace ReClassNET
1111
{
12-
public class ReClassNetProject
12+
public class ReClassNetProject : IDisposable
1313
{
1414
public delegate void ClassesChangedEvent(ClassNode sender);
1515
public event ClassesChangedEvent ClassAdded;
@@ -21,6 +21,14 @@ public class ReClassNetProject
2121

2222
public string Path { get; set; }
2323

24+
public void Dispose()
25+
{
26+
Clear();
27+
28+
ClassAdded = null;
29+
ClassRemoved = null;
30+
}
31+
2432
public void AddClass(ClassNode node)
2533
{
2634
Contract.Requires(node != null);

UI/MemoryViewControl.cs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Drawing;
66
using System.Linq;
77
using System.Windows.Forms;
8-
using ReClassNET.AddressParser;
98
using ReClassNET.DataExchange;
109
using ReClassNET.Memory;
1110
using ReClassNET.Nodes;
@@ -590,7 +589,7 @@ private void selectedNodeContextMenuStrip_Opening(object sender, CancelEventArgs
590589

591590
changeTypeToolStripMenuItem.Enabled = count > 0 && !nodeIsClass;
592591

593-
pasteNodesToolStripMenuItem.Enabled = count == 1 && ReClassClipboard.ContainsData(ReClassClipboard.Format.Nodes);
592+
pasteNodesToolStripMenuItem.Enabled = count == 1 && ReClassClipboard.ContainsNodes;
594593
removeToolStripMenuItem.Enabled = !nodeIsClass;
595594

596595
copyAddressToolStripMenuItem.Enabled = !nodeIsClass;
@@ -761,20 +760,28 @@ private void CopySelectedNodesToClipboard()
761760
{
762761
if (selectedNodes.Count > 0)
763762
{
764-
ReClassClipboard.CopyNodes(selectedNodes.Select(h => h.Node), project.Classes, Program.Logger);
763+
ReClassClipboard.Copy(selectedNodes.Select(h => h.Node), Program.Logger);
765764
}
766765
}
767766

768767
private void PasteNodeFromClipboardToSelection()
769768
{
769+
var result = ReClassClipboard.Paste(project, Program.Logger);
770+
foreach (var classNode in result.Item1)
771+
{
772+
if (!project.ContainsClass(classNode.Uuid))
773+
{
774+
project.AddClass(classNode);
775+
}
776+
}
777+
770778
if (selectedNodes.Count == 1)
771779
{
772780
var selectedNode = selectedNodes.First().Node;
773781
var parent = selectedNode.ParentNode as ClassNode;
774782
if (parent != null)
775783
{
776-
var nodes = ReClassClipboard.PasteNodes(parent, project.Classes, Program.Logger);
777-
foreach (var node in nodes)
784+
foreach (var node in result.Item2)
778785
{
779786
if (IsCycleFree(parent, node))
780787
{

0 commit comments

Comments
 (0)