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+ }
0 commit comments