~ubuntu-branches/ubuntu/oneiric/monodevelop/oneiric-updates

« back to all changes in this revision

Viewing changes to src/addins/MonoDevelop.GtkCore/lib/stetic/libsteticui/UndoQueue.cs

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-18 08:40:51 UTC
  • mfrom: (1.2.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20090218084051-gh8m6ukvokbwj7cf
Tags: 1.9.2+dfsg-1ubuntu1
* Merge from Debian Experimental (LP: #330519), remaining Ubuntu changes:
  + debian/control:
    - Update for Gnome# 2.24
    - Add libmono-cairo1.0-cil to build-deps to fool pkg-config check

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
 
2
 
using System;
3
 
using System.Xml;
4
 
using System.Collections;
5
 
 
6
 
namespace Stetic
7
 
{
8
 
        public class UndoQueue: MarshalByRefObject
9
 
        {
10
 
                ArrayList changeList = new ArrayList ();
11
 
                int undoListCount = 0;
12
 
                static UndoQueue empty = new UndoQueue ();
13
 
                
14
 
                public void AddChange (UndoRedoChange change)
15
 
                {
16
 
                        if (undoListCount < changeList.Count) {
17
 
                                // Destroy all undone changes
18
 
                                changeList.RemoveRange (undoListCount, changeList.Count - undoListCount);
19
 
                        }
20
 
                        changeList.Add (change);
21
 
                        undoListCount = changeList.Count;
22
 
                }
23
 
                
24
 
                public static UndoQueue Empty {
25
 
                        get { return empty; }
26
 
                }
27
 
                
28
 
                public bool CanUndo {
29
 
                        get { return undoListCount > 0; }
30
 
                }
31
 
                
32
 
                public bool CanRedo {
33
 
                        get { return undoListCount < changeList.Count; }
34
 
                }
35
 
                
36
 
                public void Undo ()
37
 
                {
38
 
                        if (undoListCount == 0)
39
 
                                return;
40
 
 
41
 
                        UndoRedoChange change = (UndoRedoChange) changeList [--undoListCount];
42
 
                        if (change.CheckValid ()) {
43
 
                                object res = change.ApplyChange ();
44
 
                                if (res != null)
45
 
                                        changeList [undoListCount] = res;
46
 
                                else
47
 
                                        // Undo failed
48
 
                                        changeList.RemoveAt (undoListCount);
49
 
                        } else {
50
 
                                changeList.RemoveAt (undoListCount);
51
 
                                Undo ();
52
 
                        }
53
 
                }
54
 
                
55
 
                public void Redo ()
56
 
                {
57
 
                        if (undoListCount == changeList.Count)
58
 
                                return;
59
 
                        
60
 
                        UndoRedoChange change = (UndoRedoChange) changeList [undoListCount++];
61
 
                        if (change.CheckValid ()) {
62
 
                                object res = change.ApplyChange ();
63
 
                                if (res != null)
64
 
                                        changeList [undoListCount - 1] = res;
65
 
                                else {
66
 
                                        // Redo failed
67
 
                                        undoListCount--;
68
 
                                        changeList.RemoveAt (undoListCount);
69
 
                                }
70
 
                        }
71
 
                        else {
72
 
                                changeList.RemoveAt (--undoListCount);
73
 
                                Redo ();
74
 
                        }
75
 
                }
76
 
                
77
 
                public void Purge ()
78
 
                {
79
 
                        for (int n=0; n<changeList.Count; n++) {
80
 
                                UndoRedoChange change = (UndoRedoChange) changeList [n];
81
 
                                if (!change.CheckValid()) {
82
 
                                        changeList.RemoveAt (n);
83
 
                                        if (n < undoListCount)
84
 
                                                undoListCount--;
85
 
                                }
86
 
                        }
87
 
                }
88
 
        }
89
 
        
90
 
        public abstract class UndoRedoChange: MarshalByRefObject
91
 
        {
92
 
                public abstract UndoRedoChange ApplyChange ();
93
 
 
94
 
                public virtual bool CheckValid ()
95
 
                {
96
 
                        return true;
97
 
                }
98
 
        }
99
 
        
100
 
        
101
 
        class ObjectWrapperUndoRedoChange: UndoRedoChange
102
 
        {
103
 
                UndoRedoManager manager;
104
 
                public string TargetObject;
105
 
                public object Diff;
106
 
                public ObjectWrapperUndoRedoChange Next;
107
 
                
108
 
                public ObjectWrapperUndoRedoChange (UndoRedoManager manager, string targetObject, object diff)
109
 
                {
110
 
                        this.manager = manager;
111
 
                        this.TargetObject = targetObject;
112
 
                        this.Diff = diff;
113
 
                }
114
 
                        
115
 
                public override UndoRedoChange ApplyChange ()
116
 
                {
117
 
                        return manager.ApplyChange (this);
118
 
                }
119
 
                
120
 
                public override bool CheckValid ()
121
 
                {
122
 
                        return manager.CheckValid ();
123
 
                }
124
 
        }
125
 
        
126
 
        class UndoRedoManager: IDisposable
127
 
        {
128
 
                UndoQueue queue;
129
 
                ObjectWrapper rootObject;
130
 
                bool updating;
131
 
                UndoManager undoManager = new UndoManager ();
132
 
                
133
 
                public UndoRedoManager ()
134
 
                {
135
 
                        undoManager.UndoCheckpoint += OnUndoCheckpoint;
136
 
                }
137
 
                
138
 
                public ObjectWrapper RootObject {
139
 
                        get { return rootObject; }
140
 
                        set {
141
 
                                rootObject = value;
142
 
                                undoManager.SetRoot (rootObject);
143
 
                        }
144
 
                }
145
 
                
146
 
                public UndoQueue UndoQueue {
147
 
                        get { return queue; }
148
 
                        set { queue = value; }
149
 
                }
150
 
                
151
 
                internal UndoManager UndoManager {
152
 
                        get { return undoManager; }
153
 
                }
154
 
                
155
 
                void OnUndoCheckpoint (object sender, UndoCheckpointEventArgs args)
156
 
                {
157
 
                        AddChange (args.ModifiedObjects);
158
 
                }
159
 
                
160
 
                void AddChange (ObjectWrapper[] obs)
161
 
                {
162
 
                        if (updating || queue == null)
163
 
                                return;
164
 
 
165
 
                        ObjectWrapperUndoRedoChange firstChange = null;
166
 
                        ObjectWrapperUndoRedoChange lastChange = null;
167
 
                        
168
 
//                      Console.WriteLine ("** UNDO CHECKPOINT: {0} objects", obs.Length);
169
 
                        
170
 
                        foreach (ObjectWrapper ob in obs) {
171
 
                        
172
 
                                // Get the diff for going from the new status to the old status
173
 
                                object diff = GetDiff (ob);
174
 
                                
175
 
                                if (diff == null)       // No differences
176
 
                                        continue;
177
 
                                
178
 
//                              Console.WriteLine ("ADDCHANGE " + ob + " uid:" + ob.UndoId);
179
 
//                              PrintPatch (diff);
180
 
                                
181
 
                                if (ob.UndoId == null || ob.UndoId.Length == 0)
182
 
                                        throw new InvalidOperationException ("Object of type '" + ob.GetType () + "' does not have an undo id.");
183
 
 
184
 
                                ObjectWrapperUndoRedoChange change = new ObjectWrapperUndoRedoChange (this, ob.UndoId, diff);
185
 
                                if (lastChange == null)
186
 
                                        lastChange = firstChange = change;
187
 
                                else {
188
 
                                        lastChange.Next = change;
189
 
                                        lastChange = change;
190
 
                                }
191
 
                        }
192
 
                        if (firstChange != null)
193
 
                                queue.AddChange (firstChange);
194
 
                }
195
 
                
196
 
                protected virtual object GetDiff (ObjectWrapper w)
197
 
                {
198
 
                        return w.GetUndoDiff ();
199
 
                }
200
 
                
201
 
                public UndoRedoChange ApplyChange (ObjectWrapperUndoRedoChange first)
202
 
                {
203
 
                        updating = true;
204
 
                        
205
 
                        try {
206
 
                                ObjectWrapperUndoRedoChange change = first;
207
 
                                ObjectWrapperUndoRedoChange lastRedo = null;
208
 
                                while (change != null) {
209
 
                                        ObjectWrapperUndoRedoChange redo = ApplyDiff (change.TargetObject, change.Diff);
210
 
                                        if (redo != null) {
211
 
                                                redo.Next = lastRedo;
212
 
                                                lastRedo = redo;
213
 
                                        }
214
 
                                        change = change.Next;
215
 
                                }
216
 
                                return lastRedo;
217
 
                        } catch (Exception ex) {
218
 
                                Console.WriteLine (ex);
219
 
                                return null;
220
 
                        } finally {
221
 
                                updating = false;
222
 
                        }
223
 
                }
224
 
                
225
 
                ObjectWrapperUndoRedoChange ApplyDiff (string id, object diff)
226
 
                {
227
 
//                      Console.WriteLine ("** APPLYING DIFF: uid:" + id);
228
 
//                      PrintPatch (diff);
229
 
                        
230
 
                        ObjectWrapper ww = rootObject.FindObjectByUndoId (id);
231
 
                        if (ww == null) {
232
 
                                Console.WriteLine ("Object with undo id '{0}' not found", id);
233
 
                                return null;
234
 
                        }
235
 
                        
236
 
                        object reverseDiff = ww.ApplyUndoRedoDiff (diff);
237
 
                
238
 
                        if (reverseDiff != null) {
239
 
//                              Console.WriteLine ("** REVERSE DIFF:");
240
 
//                              PrintPatch (reverseDiff);
241
 
                                
242
 
                                ObjectWrapperUndoRedoChange change = new ObjectWrapperUndoRedoChange (this, id, reverseDiff);
243
 
                                return change;
244
 
                        } else
245
 
                                return null;
246
 
                }
247
 
                
248
 
                internal bool CheckValid ()
249
 
                {
250
 
                        return rootObject != null;
251
 
                }
252
 
                
253
 
                public void Dispose ()
254
 
                {
255
 
                        rootObject = null;
256
 
                        if (queue != null)
257
 
                                queue.Purge ();
258
 
                }
259
 
                
260
 
                internal void PrintPatch (object diff)
261
 
                {
262
 
                        if (diff is Array) {
263
 
                                foreach (object ob in (Array)diff)
264
 
                                        if (ob != null) PrintPatch (ob);
265
 
                        } else if (diff is XmlElement)
266
 
                                Console.WriteLine (((XmlElement)diff).OuterXml);
267
 
                        else
268
 
                                Console.WriteLine (diff.ToString ());
269
 
                }
270
 
        }
271
 
}
272