Skip to content

Commit fb7b4d6

Browse files
committed
Initial undo/redo system in place. Class name is now undo/redo aware
1 parent 35afcee commit fb7b4d6

File tree

6 files changed

+110
-5
lines changed

6 files changed

+110
-5
lines changed

ReClass.NET/Constants.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace ReClassNET
1+
namespace ReClassNET
22
{
33
public class Constants
44
{
@@ -39,5 +39,14 @@ public static class CommandLineOptions
3939
public const string FileExtRegister = "registerfileext";
4040
public const string FileExtUnregister = "unregisterfileext";
4141
}
42+
43+
/// <summary>
44+
/// Change type for commandified members in classes which is used to signal what change occurred exactly. As we don't use this feature of the commandified
45+
/// class, this enum is defined to simply signal 'no specific change other than it changed' happened.
46+
/// </summary>
47+
public enum GeneralPurposeChangeType
48+
{
49+
None
50+
}
4251
}
4352
}

ReClass.NET/Forms/MainForm.Designer.cs

Lines changed: 27 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ReClass.NET/Forms/MainForm.Functions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using ReClassNET.Nodes;
1717
using ReClassNET.Project;
1818
using ReClassNET.UI;
19+
using SD.Tools.Algorithmia.Commands;
1920

2021
namespace ReClassNET.Forms
2122
{
@@ -213,6 +214,10 @@ public void LoadProjectFromPath(string path)
213214
{
214215
Contract.Requires(path != null);
215216

217+
CommandQueueManagerSingleton.GetInstance().ResetActiveCommandQueue();
218+
CommandQueueManagerSingleton.GetInstance().BeginNonUndoablePeriod(); // we don't want to trigger undo/redo activity while loading
219+
CommandQueueManagerSingleton.GetInstance().RaiseEvents = false;
220+
216221
var project = new ReClassNetProject();
217222

218223
LoadProjectFromPath(path, ref project);
@@ -224,6 +229,10 @@ public void LoadProjectFromPath(string path)
224229
}
225230

226231
SetProject(project);
232+
233+
// Done loading, resume undo/redo activity
234+
CommandQueueManagerSingleton.GetInstance().RaiseEvents = true;
235+
CommandQueueManagerSingleton.GetInstance().EndNonUndoablePeriod();
227236
}
228237

229238
/// <summary>Loads the file into the given project.</summary>

ReClass.NET/Forms/MainForm.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using ReClassNET.UI;
2323
using ReClassNET.Util;
2424
using ReClassNET.Util.Conversion;
25+
using SD.Tools.Algorithmia.Commands;
2526

2627
namespace ReClassNET.Forms
2728
{
@@ -95,8 +96,11 @@ public MainForm()
9596
};
9697

9798
pluginManager = new PluginManager(new DefaultPluginHost(this, Program.RemoteProcess, Program.Logger));
99+
100+
CommandQueueManagerSingleton.GetInstance().CommandQueueActionPerformed += OnCommandQueueActionPerformed;
98101
}
99102

103+
100104
protected override void OnLoad(EventArgs e)
101105
{
102106
base.OnLoad(e);
@@ -135,6 +139,8 @@ protected override void OnLoad(EventArgs e)
135139
{
136140
AttachToProcess(Program.CommandLineArgs[Constants.CommandLineOptions.AttachTo]);
137141
}
142+
143+
SetStateOfUndoRedoButtons();
138144
}
139145

140146
protected override void OnFormClosed(FormClosedEventArgs e)
@@ -1063,7 +1069,36 @@ private void initClassToolStripMenuItem_Click(object sender, EventArgs e)
10631069
{
10641070
return;
10651071
}
1072+
1073+
var cmd = new UndoablePeriodCommand("InitClassFromRTTI");
1074+
CommandQueueManagerSingleton.GetInstance().BeginUndoablePeriod(cmd);
10661075
memoryViewControl.InitCurrentClassFromRTTI(node as ClassNode);
1076+
CommandQueueManagerSingleton.GetInstance().EndUndoablePeriod(cmd);
1077+
}
1078+
1079+
1080+
private void SetStateOfUndoRedoButtons()
1081+
{
1082+
undoToolbarMenuItem.Enabled = CommandQueueManagerSingleton.GetInstance().CanUndo(Program.CommandQueueID);
1083+
redoToolbarMenuItem.Enabled = CommandQueueManagerSingleton.GetInstance().CanDo(Program.CommandQueueID);
1084+
}
1085+
1086+
1087+
private void OnCommandQueueActionPerformed(object sender, CommandQueueActionPerformedEventArgs e)
1088+
{
1089+
SetStateOfUndoRedoButtons();
1090+
}
1091+
1092+
1093+
private void undoToolbarMenuItem_Click(object sender, EventArgs e)
1094+
{
1095+
CommandQueueManagerSingleton.GetInstance().UndoLastCommand();
1096+
}
1097+
1098+
1099+
private void redoToolbarMenuItem_Click(object sender, EventArgs e)
1100+
{
1101+
CommandQueueManagerSingleton.GetInstance().RedoLastCommand();
10671102
}
10681103
}
10691104
}

ReClass.NET/Nodes/BaseNode.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using ReClassNET.Extensions;
88
using ReClassNET.UI;
99
using ReClassNET.Util;
10+
using SD.Tools.Algorithmia.GeneralDataStructures;
11+
using SD.Tools.Algorithmia.GeneralDataStructures.EventArguments;
1012

1113
namespace ReClassNET.Nodes
1214
{
@@ -24,14 +26,26 @@ public abstract class BaseNode
2426

2527
private static int nodeIndex = 0;
2628

27-
private string name = string.Empty;
29+
//private string name = string.Empty;
30+
private CommandifiedMember<string, Constants.GeneralPurposeChangeType> name;
2831
private string comment = string.Empty;
2932

3033
/// <summary>Gets or sets the offset of the node.</summary>
3134
public int Offset { get; set; }
3235

3336
/// <summary>Gets or sets the name of the node. If a new name was set the property changed event gets fired.</summary>
34-
public virtual string Name { get => name; set { if (value != null && name != value) { name = value; NameChanged?.Invoke(this); } } }
37+
public virtual string Name
38+
{
39+
get => name.MemberValue;
40+
set
41+
{
42+
if (value == null)
43+
{
44+
return;
45+
}
46+
name.MemberValue = value;
47+
}
48+
}
3549

3650
/// <summary>Gets or sets the comment of the node.</summary>
3751
public string Comment { get => comment; set { if (value != null && comment != value) { comment = value; CommentChanged?.Invoke(this); } } }
@@ -100,12 +114,15 @@ protected BaseNode()
100114
Contract.Ensures(name != null);
101115
Contract.Ensures(comment != null);
102116

103-
Name = $"N{nodeIndex++:X08}";
117+
name = new CommandifiedMember<string, Constants.GeneralPurposeChangeType>("Name", Constants.GeneralPurposeChangeType.None, $"N{nodeIndex++:X08}");
118+
name.ValueChanged += Name_ValueChanged;
104119
Comment = string.Empty;
105120

106121
LevelsOpen[0] = true;
107122
}
108123

124+
private void Name_ValueChanged(object sender, MemberChangedEventArgs<Constants.GeneralPurposeChangeType, string> e) => NameChanged?.Invoke(this);
125+
109126
public abstract void GetUserInterfaceInfo(out string name, out Image icon);
110127

111128
public virtual bool UseMemoryPreviewToolTip(HotSpot spot, out IntPtr address)

ReClass.NET/Program.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using ReClassNET.Native;
1212
using ReClassNET.UI;
1313
using ReClassNET.Util;
14+
using SD.Tools.Algorithmia.Commands;
1415

1516
namespace ReClassNET
1617
{
@@ -34,10 +35,13 @@ public static class Program
3435

3536
public static FontEx MonoSpaceFont { get; private set; }
3637

38+
public static Guid CommandQueueID { get; private set; }
39+
3740
[STAThread]
3841
static void Main(string[] args)
3942
{
4043
DesignMode = false; // The designer doesn't call Main()
44+
CommandQueueID = Guid.NewGuid();
4145

4246
CommandLineArgs = new CommandLineArgs(args);
4347

@@ -63,6 +67,11 @@ static void Main(string[] args)
6367
Application.EnableVisualStyles();
6468
Application.SetCompatibleTextRenderingDefault(false);
6569

70+
// switch is set to false, so Do actions during Undo actions are ignored.
71+
CommandQueueManager.ThrowExceptionOnDoDuringUndo = false;
72+
// activate our command queue stack. We're only changing things from the main thread so we don't need multiple stacks.
73+
CommandQueueManagerSingleton.GetInstance().ActivateCommandQueueStack(CommandQueueID);
74+
6675
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
6776

6877
Settings = SettingsSerializer.Load();

0 commit comments

Comments
 (0)