Skip to content

Commit f605055

Browse files
committed
added UI EditSession
1 parent 56035d0 commit f605055

File tree

4 files changed

+182
-0
lines changed

4 files changed

+182
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.ComponentModel.DataAnnotations;
4+
using System.Linq;
5+
6+
namespace Eocron.Algorithms.UI.Editing;
7+
8+
public class EditSession<TDocument> : IEditSession<TDocument>
9+
{
10+
public TDocument Source { get; private set; }
11+
public TDocument Draft { get; private set; }
12+
public ValidationResult[] Validation { get; private set; }
13+
public bool IsEditing { get; private set; }
14+
public bool CanRedo => _lastChangeIndex < (_changes.Count - 1);
15+
public bool CanUndo => _lastChangeIndex >= 0;
16+
17+
public EditSession(TDocument source, int changeLimit = 100)
18+
{
19+
_changeLimit = changeLimit;
20+
Source = source!;
21+
}
22+
23+
public void BeginEdit()
24+
{
25+
ValidateNotEditing();
26+
Draft = EditSessionHelper.DeepClone(Source);
27+
IsEditing = true;
28+
}
29+
30+
public void Apply(IEditSessionChange<TDocument> change)
31+
{
32+
ValidateEditing();
33+
change.Redo(Draft);
34+
while (_changes.Count >= _changeLimit)
35+
{
36+
_changes.RemoveAt(0);
37+
_lastChangeIndex--;
38+
}
39+
40+
var tailStartIndex = _lastChangeIndex + 1;
41+
if (tailStartIndex < _changes.Count)
42+
{
43+
_changes.RemoveRange(tailStartIndex, _changes.Count - tailStartIndex);
44+
}
45+
46+
_changes.Add(change);
47+
_lastChangeIndex++;
48+
}
49+
50+
public bool TryCommit()
51+
{
52+
ValidateEditing();
53+
Validation = OnValidate(Draft);
54+
55+
if (Validation.All(x => x.ErrorMessage == null))
56+
{
57+
return false;
58+
}
59+
60+
_changes.Clear();
61+
_lastChangeIndex = -1;
62+
Validation = [];
63+
Source = Draft;
64+
Draft = default;
65+
IsEditing = false;
66+
return true;
67+
}
68+
69+
public void Rollback()
70+
{
71+
ValidateEditing();
72+
Validation = [];
73+
_changes.Clear();
74+
_lastChangeIndex = -1;
75+
Draft = default;
76+
IsEditing = false;
77+
}
78+
79+
public void Undo()
80+
{
81+
ValidateEditing();
82+
if (CanUndo)
83+
{
84+
_changes[_lastChangeIndex--].Undo(Draft);
85+
Validation = [];
86+
}
87+
}
88+
89+
public void Redo()
90+
{
91+
ValidateEditing();
92+
if (CanRedo)
93+
{
94+
_changes[++_lastChangeIndex].Redo(Draft);
95+
Validation = [];
96+
}
97+
}
98+
99+
protected virtual ValidationResult[] OnValidate(TDocument draft)
100+
{
101+
return [];
102+
}
103+
104+
private void ValidateEditing()
105+
{
106+
if (!IsEditing)
107+
{
108+
throw new ArgumentException("Editing is not allowed");
109+
}
110+
}
111+
112+
private void ValidateNotEditing()
113+
{
114+
if (IsEditing)
115+
{
116+
throw new ArgumentException("Editing is allowed");
117+
}
118+
}
119+
120+
private readonly int _changeLimit;
121+
private readonly List<IEditSessionChange<TDocument>> _changes = new();
122+
private int _lastChangeIndex = -1;
123+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using Newtonsoft.Json;
2+
3+
namespace Eocron.Algorithms.UI.Editing;
4+
5+
public static class EditSessionHelper
6+
{
7+
public static T DeepClone<T>(T source)
8+
{
9+
if (source == null)
10+
{
11+
return default;
12+
}
13+
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, Settings), Settings);
14+
}
15+
16+
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings()
17+
{
18+
TypeNameHandling = TypeNameHandling.Objects
19+
};
20+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System.ComponentModel.DataAnnotations;
2+
3+
namespace Eocron.Algorithms.UI.Editing
4+
{
5+
public interface IEditSession<out TDocument>
6+
{
7+
TDocument Source { get; }
8+
9+
TDocument Draft { get; }
10+
11+
ValidationResult[] Validation { get; }
12+
13+
bool IsEditing { get; }
14+
15+
bool CanRedo { get; }
16+
17+
bool CanUndo { get; }
18+
19+
void BeginEdit();
20+
21+
void Apply(IEditSessionChange<TDocument> change);
22+
23+
bool TryCommit();
24+
25+
void Rollback();
26+
27+
void Undo();
28+
29+
void Redo();
30+
}
31+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace Eocron.Algorithms.UI.Editing
2+
{
3+
public interface IEditSessionChange<in TDocument>
4+
{
5+
void Redo(TDocument document);
6+
void Undo(TDocument document);
7+
}
8+
}

0 commit comments

Comments
 (0)