Code

Change layout to be more space conserving. This allows a larger paper list
[inkscape.git] / src / event-log.cpp
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"
13 #include "event-log.h"
14 #include "inkscape.h"
15 #include "util/ucompose.hpp"
17 namespace Inkscape {
19 EventLog::EventLog() :
20     UndoStackObserver(),
21     _connected (false),
22     _document (NULL),
23     _event_list_store (Gtk::TreeStore::create(_columns)),
24     _event_list_selection (NULL),
25     _event_list_view (NULL),
26     _curr_event_parent (NULL),
27     _notifications_blocked (false),
28     _callback_connections (NULL)
29 {
30     // add initial pseudo event
31     Gtk::TreeRow curr_row = *(_event_list_store->append());
32     _curr_event = _last_event = curr_row;
33     
34     curr_row[_columns.description] = _("[Unchanged]");
35     curr_row[_columns.type] = SP_VERB_FILE_NEW;
36 }
38 EventLog::~EventLog() { }
40 void
41 EventLog::notifyUndoEvent(Event* log) 
42 {
43     if ( !_notifications_blocked ) {
44     
45         // if we're on the first child event...
46         if ( _curr_event->parent() &&
47              _curr_event == _curr_event->parent()->children().begin() )
48         {
49             // ...back up to the parent
50             _curr_event = _curr_event->parent();
51             _curr_event_parent = (iterator)NULL;
53         } else {
55             // if we're about to leave a branch, collapse it
56             if ( !_curr_event->children().empty() && _connected ) {
57                 (*_callback_connections)[CALLB_COLLAPSE].block();
58                 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event));
59                 (*_callback_connections)[CALLB_COLLAPSE].block(false);
60             }
62             --_curr_event;
64             // if we're entering a branch, move to the end of it
65             if (!_curr_event->children().empty()) {
66                 _curr_event_parent = _curr_event;
67                 _curr_event = _curr_event->children().end();
68                 --_curr_event;
69             }
70         }
72         // update the view
73         if (_connected) {
74             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
75             (*_callback_connections)[CALLB_EXPAND].block();
77             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
78             _event_list_view->expand_to_path(curr_path);
79             _event_list_selection->select(curr_path);
80             _event_list_view->scroll_to_row(curr_path);  
82             (*_callback_connections)[CALLB_EXPAND].block(false);
83             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
84         }
86         updateUndoVerbs();
87     }
89 }
91 void
92 EventLog::notifyRedoEvent(Event* log)
93 {
94     if ( !_notifications_blocked ) {
96         // if we're on a parent event...
97         if ( !_curr_event->children().empty() ) {
99             // ...move to its first child
100             _curr_event_parent = _curr_event;
101             _curr_event = _curr_event->children().begin();
103         } else {
104         
105             ++_curr_event;
107             // if we are about to leave a branch...
108             if ( _curr_event->parent() &&
109                  _curr_event == _curr_event->parent()->children().end() )
110             {
112                 // ...collapse it
113                 if (_connected) {
114                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
115                     (*_callback_connections)[CALLB_COLLAPSE].block();
116                     _event_list_view->collapse_row(_event_list_store->get_path(_curr_event->parent()));
117                     (*_callback_connections)[CALLB_COLLAPSE].block(false);
118                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
119                 }
121                 // ...and move to the next event at parent level
122                 _curr_event = _curr_event->parent();
123                 _curr_event_parent = (iterator)NULL;
125                 ++_curr_event;
126             }
127         }
129         // update the view
130         if (_connected) {
131             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
133             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
134             (*_callback_connections)[CALLB_EXPAND].block();
136             _event_list_view->expand_to_path(curr_path);
137             _event_list_selection->select(curr_path);
138             _event_list_view->scroll_to_row(curr_path);  
140             (*_callback_connections)[CALLB_EXPAND].block(false);
141             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
142         }
144         updateUndoVerbs();
145     }
149 void 
150 EventLog::notifyUndoCommitEvent(Event* log)
152     // If we're not at the last event in list then erase the previously undone events 
153     if ( _last_event != _curr_event ) {
155         _last_event = _curr_event;
157         if ( !_last_event->children().empty() ) {
158             _last_event = _last_event->children().begin();
159         } else {
160             ++_last_event;
161         }
163         while ( _last_event != _event_list_store->children().end() ) {
165             if (_last_event->parent()) {
166                 while ( _last_event != _last_event->parent()->children().end() ) {
167                     _last_event = _event_list_store->erase(_last_event);
168                 }
169                 _last_event = _last_event->parent();
171                 (*_last_event)[_columns.child_count] = _last_event->children().size() + 1;
173                 ++_last_event;
174             } else {
175                 _last_event = _event_list_store->erase(_last_event);
176             }
178         }
179     }
181     const unsigned int event_type = log->type;
183     Gtk::TreeRow curr_row;
185     // if the new event is of the same type as the previous then create a new branch
186     if ( event_type == (*_curr_event)[_columns.type] ) {
187         if ( !_curr_event_parent ) {
188             _curr_event_parent = _curr_event;
189         }
190         curr_row = *(_event_list_store->append(_curr_event_parent->children()));
191         (*_curr_event_parent)[_columns.child_count] = _curr_event_parent->children().size() + 1;
192     } else {
193         curr_row = *(_event_list_store->append());
194         curr_row[_columns.child_count] = 1;
196         _curr_event = _last_event = curr_row;
198         // collapse if we're leaving a branch
199         if (_curr_event_parent && _connected) {
200             (*_callback_connections)[CALLB_COLLAPSE].block();
201             _event_list_view->collapse_row(_event_list_store->get_path(_curr_event_parent));
202             (*_callback_connections)[CALLB_COLLAPSE].block(false);
203         }
205         _curr_event_parent = (iterator)(NULL);
206     }      
208     _curr_event = _last_event = curr_row;
210     curr_row[_columns.type] = event_type;
211     curr_row[_columns.description] = log->description;
213     // update the view
214     if (_connected) {
215         Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
217         (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
218         (*_callback_connections)[CALLB_EXPAND].block();
220         _event_list_view->expand_to_path(curr_path);
221         _event_list_selection->select(curr_path);
222         _event_list_view->scroll_to_row(curr_path);  
224         (*_callback_connections)[CALLB_EXPAND].block(false);
225         (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
226     }
228     updateUndoVerbs();
232 void
233 EventLog::setDocument(SPDocument *document)
235     _document = document;
236     updateUndoVerbs();
240 void 
241 EventLog::connectWithDialog(Gtk::TreeView *event_list_view, CallbackMap *callback_connections)
243     _event_list_view = event_list_view;
244     _event_list_selection = event_list_view->get_selection();
245     _event_list_selection->set_mode(Gtk::SELECTION_SINGLE);
247     _callback_connections = callback_connections;
249     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
250     (*_callback_connections)[CALLB_EXPAND].block();
252     _event_list_view->expand_to_path(_event_list_store->get_path(_curr_event));
253     _event_list_selection->select(_curr_event);
255     (*_callback_connections)[CALLB_EXPAND].block(false);
256     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
258     _connected = true;
261 void
262 EventLog::updateUndoVerbs()
264     if(_document) {
266         if(_getUndoEvent()) { 
267             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, true);
269             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, String::ucompose("%1: %2", 
270                       Glib::ustring(_("_Undo")),
271                       Glib::ustring((*_getUndoEvent())[_columns.description])));
272         } else {
273             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, _("_Undo"));
274             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, false);
275         }
277         if(_getRedoEvent()) {
278             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, true);
279             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, String::ucompose("%1: %2", 
280                       Glib::ustring(_("_Redo")),
281                       Glib::ustring((*_getRedoEvent())[_columns.description])));
283         } else {
284             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, _("_Redo"));
285             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, false);
286         }
288     }
293 EventLog::const_iterator
294 EventLog::_getUndoEvent() const
296     const_iterator undo_event = (const_iterator)NULL;
297     if( _curr_event != _event_list_store->children().begin() )
298         undo_event = _curr_event;
299     return undo_event;
302 EventLog::const_iterator
303 EventLog::_getRedoEvent() const
305     const_iterator redo_event = (const_iterator)NULL;
307     if ( _curr_event != _last_event ) {
309         if ( !_curr_event->children().empty() )
310             redo_event = _curr_event->children().begin();
311         else  {
312             redo_event = _curr_event;
313             ++redo_event;
315             if ( redo_event->parent() &&
316                  redo_event == redo_event->parent()->children().end() ) {
318                 redo_event = redo_event->parent();
319                 ++redo_event;
321             }
322         }
324     }
326     return redo_event;
331 /*
332   Local Variables:
333   mode:c++
334   c-file-style:"stroustrup"
335   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
336   indent-tabs-mode:nil
337   fill-column:99
338   End:
339 */
340 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :