Initial commit
[fillmore] / src / marina / UndoManager.vala
1 /* Copyright 2009 Yorba Foundation
2  *
3  * This software is licensed under the GNU Lesser General Public License
4  * (version 2.1 or later).  See the COPYING file in this distribution. 
5  */
6
7 namespace Model {
8 public class UndoManager {
9     int saved_index = 0;
10     bool _in_undo = false;
11     Gee.ArrayList<Command> command_list = new Gee.ArrayList<Command>();
12     public bool is_dirty { get { return saved_index != command_list.size; } }
13     public bool can_undo { get { return command_list.size > 0; } }
14     public bool in_undo { get { return _in_undo; } private set { _in_undo = value; } }
15
16     public signal void undo_changed(bool can_undo);
17     public signal void dirty_changed(bool is_dirty);
18
19     public class UndoManager() {
20     }
21     
22     public void reset() {
23         command_list.clear();
24         saved_index = 0;
25         undo_changed(false);
26     }
27     
28     public void mark_clean() {
29         saved_index = command_list.size;
30         dirty_changed(false);
31     }
32
33     public void start_transaction(string description) {
34         TransactionCommand command = new TransactionCommand(false, description);
35         command_list.add(command);
36         undo_changed(true);
37     }
38
39     public void end_transaction(string description) {
40         TransactionCommand command = new TransactionCommand(true, description);
41         command_list.add(command);
42         undo_changed(true);
43     }
44
45     public void do_command(Command the_command) {
46         if (!in_undo) {
47             the_command.apply();
48             Command? current_command = get_current_command();
49             if (current_command == null || !current_command.merge(the_command)) {
50                 command_list.add(the_command);
51             }
52             dirty_changed(true);
53             undo_changed(can_undo);
54         }
55     }
56
57     Command? get_current_command() {
58         int index = command_list.size - 1;
59         if (index >= 0) {
60             return command_list[index];
61         } else {
62             return null;
63         }
64     }
65
66     public void undo() {
67         assert(in_undo == false);
68         in_undo = true;
69         int in_transaction = 0;
70         do {
71             Command? the_command = get_current_command();
72             if (the_command != null) {
73                 command_list.remove(the_command);
74                 TransactionCommand transaction_command = the_command as TransactionCommand;
75                 if (transaction_command != null) {
76                     if (transaction_command.in_transaction()) {
77                         in_transaction++;
78                     } else {
79                         in_transaction--;
80                     }
81                 } else {
82                     the_command.undo();
83                 }
84             } else {
85                 break;
86             }
87         } while (in_transaction > 0);
88         dirty_changed(is_dirty);
89         undo_changed(can_undo);
90         in_undo = false;
91     }
92     
93     public string get_undo_title() {
94         Command? the_command = get_current_command();
95         if (the_command != null) {
96             return the_command.description();
97         } else {
98             return "";
99         }
100     }
101     
102 }
103 }