1 /*
2 * Author:
3 * Gustav Broberg <broberg@kth.se>
4 *
5 * Copyright (c) 2006 Authors
6 *
7 * Released under GNU GPL, read the file 'COPYING' for more information
8 */
10 #include <glibmm/i18n.h>
12 #include "desktop.h"
14 #include "event-log.h"
16 namespace Inkscape {
18 EventLog::EventLog() :
19 UndoStackObserver(),
20 _connected (false),
21 _event_list_store (Gtk::TreeStore::create(_columns)),
22 _event_list_selection (NULL),
23 _event_list_view (NULL),
24 _curr_event_parent (NULL),
25 _notifications_blocked (false),
26 _callback_connections (NULL)
27 {
28 // add initial pseudo event
29 Gtk::TreeRow curr_row = *(_event_list_store->append());
30 _curr_event = _last_event = curr_row;
32 curr_row[_columns.description] = _("[Unchanged]");
33 curr_row[_columns.type] = SP_VERB_FILE_NEW;
34 }
36 EventLog::~EventLog() { }
38 void
39 EventLog::notifyUndoEvent(Event* log)
40 {
41 if ( !_notifications_blocked ) {
43 // if we're on the first child event...
44 if ( _curr_event->parent() &&
45 _curr_event == _curr_event->parent()->children().begin() )
46 {
47 // ...back up to the parent
48 _curr_event = _curr_event->parent();
49 _curr_event_parent = (iterator)NULL;
51 } else {
53 // if we're about to leave a branch, collapse it
54 if ( !_curr_event->children().empty() && _connected ) {
55 (*_callback_connections)[CALLB_COLLAPSE].block();
56 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event));
57 (*_callback_connections)[CALLB_COLLAPSE].block(false);
58 }
60 --_curr_event;
62 // if we're entering a branch, move to the end of it
63 if (!_curr_event->children().empty()) {
64 _curr_event_parent = _curr_event;
65 _curr_event = _curr_event->children().end();
66 --_curr_event;
67 }
68 }
70 // update the view
71 if (_connected) {
72 (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
73 (*_callback_connections)[CALLB_EXPAND].block();
75 Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
76 _event_list_view->expand_to_path(curr_path);
77 _event_list_selection->select(curr_path);
78 _event_list_view->scroll_to_row(curr_path);
80 (*_callback_connections)[CALLB_EXPAND].block(false);
81 (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
82 }
84 }
85 }
87 void
88 EventLog::notifyRedoEvent(Event* log)
89 {
90 if ( !_notifications_blocked ) {
92 // if we're on a parent event...
93 if ( !_curr_event->children().empty() ) {
95 // ...move to its first child
96 _curr_event_parent = _curr_event;
97 _curr_event = _curr_event->children().begin();
99 } else {
101 ++_curr_event;
103 // if we are about to leave a branch...
104 if ( _curr_event->parent() &&
105 _curr_event == _curr_event->parent()->children().end() )
106 {
108 // ...collapse it
109 if (_connected) {
110 (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
111 (*_callback_connections)[CALLB_COLLAPSE].block();
112 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event->parent()));
113 (*_callback_connections)[CALLB_COLLAPSE].block(false);
114 (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
115 }
117 // ...and move to the next event at parent level
118 _curr_event = _curr_event->parent();
119 _curr_event_parent = (iterator)NULL;
121 ++_curr_event;
122 }
123 }
125 // update the view
126 if (_connected) {
127 Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
129 (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
130 (*_callback_connections)[CALLB_EXPAND].block();
132 _event_list_view->expand_to_path(curr_path);
133 _event_list_selection->select(curr_path);
134 _event_list_view->scroll_to_row(curr_path);
136 (*_callback_connections)[CALLB_EXPAND].block(false);
137 (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
138 }
140 }
141 }
143 void
144 EventLog::notifyUndoCommitEvent(Event* log)
145 {
146 // If we're not at the last event in list then erase the previously undone events
147 if ( _last_event != _curr_event ) {
149 _last_event = _curr_event;
151 if ( !_last_event->children().empty() ) {
152 _last_event = _last_event->children().begin();
153 } else {
154 ++_last_event;
155 }
157 while ( _last_event != _event_list_store->children().end() ) {
159 if (_last_event->parent()) {
160 while ( _last_event != _last_event->parent()->children().end() ) {
161 _last_event = _event_list_store->erase(_last_event);
162 }
163 _last_event = _last_event->parent();
165 (*_last_event)[_columns.child_count] = _last_event->children().size() + 1;
167 ++_last_event;
168 } else {
169 _last_event = _event_list_store->erase(_last_event);
170 }
172 }
173 }
175 const unsigned int event_type = log->type;
177 Gtk::TreeRow curr_row;
179 // if the new event is of the same type as the previous then create a new branch
180 if ( event_type == (*_curr_event)[_columns.type] ) {
181 if ( !_curr_event_parent ) {
182 _curr_event_parent = _curr_event;
183 }
184 curr_row = *(_event_list_store->append(_curr_event_parent->children()));
185 (*_curr_event_parent)[_columns.child_count] = _curr_event_parent->children().size() + 1;
186 } else {
187 curr_row = *(_event_list_store->append());
188 curr_row[_columns.child_count] = 1;
190 _curr_event = _last_event = curr_row;
192 // collapse if we're leaving a branch
193 if (_curr_event_parent && _connected) {
194 (*_callback_connections)[CALLB_COLLAPSE].block();
195 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event_parent));
196 (*_callback_connections)[CALLB_COLLAPSE].block(false);
197 }
199 _curr_event_parent = (iterator)(NULL);
200 }
202 _curr_event = _last_event = curr_row;
204 curr_row[_columns.type] = event_type;
205 curr_row[_columns.description] = log->description;
207 // update the view
208 if (_connected) {
209 Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
211 (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
212 (*_callback_connections)[CALLB_EXPAND].block();
214 _event_list_view->expand_to_path(curr_path);
215 _event_list_selection->select(curr_path);
216 _event_list_view->scroll_to_row(curr_path);
218 (*_callback_connections)[CALLB_EXPAND].block(false);
219 (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
220 }
222 }
224 void
225 EventLog::connectWithDialog(Gtk::TreeView *event_list_view, CallbackMap *callback_connections)
226 {
227 _event_list_view = event_list_view;
228 _event_list_selection = event_list_view->get_selection();
229 _event_list_selection->set_mode(Gtk::SELECTION_SINGLE);
231 _callback_connections = callback_connections;
233 (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
234 (*_callback_connections)[CALLB_EXPAND].block();
236 _event_list_view->expand_to_path(_event_list_store->get_path(_curr_event));
237 _event_list_selection->select(_curr_event);
239 (*_callback_connections)[CALLB_EXPAND].block(false);
240 (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
242 _connected = true;
243 }
245 }
246 /*
247 Local Variables:
248 mode:c++
249 c-file-style:"stroustrup"
250 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
251 indent-tabs-mode:nil
252 fill-column:99
253 End:
254 */
255 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :