Code

Switched pen and pencil toobars to stock GTK+ toolbars
[inkscape.git] / src / event-log.cpp
1 /*
2  * Author:
3  *   Gustav Broberg <broberg@kth.se>
4  *
5  * Copyright (c) 2006, 2007 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(SPDocument* document) :
20     UndoStackObserver(),
21     _connected (false),
22     _document (document),
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         // make sure the supplied event matches the next undoable event
46         g_return_if_fail ( _getUndoEvent() && (*(_getUndoEvent()))[_columns.event] == log );
48         // if we're on the first child event...
49         if ( _curr_event->parent() &&
50              _curr_event == _curr_event->parent()->children().begin() )
51         {
52             // ...back up to the parent
53             _curr_event = _curr_event->parent();
54             _curr_event_parent = (iterator)NULL;
56         } else {
58             // if we're about to leave a branch, collapse it
59             if ( !_curr_event->children().empty() && _connected ) {
60                 (*_callback_connections)[CALLB_COLLAPSE].block();
61                 _event_list_view->collapse_row(_event_list_store->get_path(_curr_event));
62                 (*_callback_connections)[CALLB_COLLAPSE].block(false);
63             }
65             --_curr_event;
67             // if we're entering a branch, move to the end of it
68             if (!_curr_event->children().empty()) {
69                 _curr_event_parent = _curr_event;
70                 _curr_event = _curr_event->children().end();
71                 --_curr_event;
72             }
73         }
75         // update the view
76         if (_connected) {
77             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
78             (*_callback_connections)[CALLB_EXPAND].block();
80             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
81             _event_list_view->expand_to_path(curr_path);
82             _event_list_selection->select(curr_path);
83             _event_list_view->scroll_to_row(curr_path);
85             (*_callback_connections)[CALLB_EXPAND].block(false);
86             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
87         }
89         updateUndoVerbs();
90     }
92 }
94 void
95 EventLog::notifyRedoEvent(Event* log)
96 {
97     if ( !_notifications_blocked ) {
99         // make sure the supplied event matches the next redoable event
100         g_return_if_fail ( _getRedoEvent() && (*(_getRedoEvent()))[_columns.event] == log );
102         // if we're on a parent event...
103         if ( !_curr_event->children().empty() ) {
105             // ...move to its first child
106             _curr_event_parent = _curr_event;
107             _curr_event = _curr_event->children().begin();
109         } else {
110         
111             ++_curr_event;
113             // if we are about to leave a branch...
114             if ( _curr_event->parent() &&
115                  _curr_event == _curr_event->parent()->children().end() )
116             {
118                 // ...collapse it
119                 if (_connected) {
120                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
121                     (*_callback_connections)[CALLB_COLLAPSE].block();
122                     _event_list_view->collapse_row(_event_list_store->get_path(_curr_event->parent()));
123                     (*_callback_connections)[CALLB_COLLAPSE].block(false);
124                     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
125                 }
127                 // ...and move to the next event at parent level
128                 _curr_event = _curr_event->parent();
129                 _curr_event_parent = (iterator)NULL;
131                 ++_curr_event;
132             }
133         }
135         // update the view
136         if (_connected) {
137             Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
139             (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
140             (*_callback_connections)[CALLB_EXPAND].block();
142             _event_list_view->expand_to_path(curr_path);
143             _event_list_selection->select(curr_path);
144             _event_list_view->scroll_to_row(curr_path);
146             (*_callback_connections)[CALLB_EXPAND].block(false);
147             (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
148         }
150         updateUndoVerbs();
151     }
155 void 
156 EventLog::notifyUndoCommitEvent(Event* log)
158     _clearRedo();
160     const unsigned int event_type = log->type;
162     Gtk::TreeRow curr_row;
164     // if the new event is of the same type as the previous then create a new branch
165     if ( event_type == (*_curr_event)[_columns.type] ) {
166         if ( !_curr_event_parent ) {
167             _curr_event_parent = _curr_event;
168         }
169         curr_row = *(_event_list_store->append(_curr_event_parent->children()));
170         (*_curr_event_parent)[_columns.child_count] = _curr_event_parent->children().size() + 1;
171     } else {
172         curr_row = *(_event_list_store->append());
173         curr_row[_columns.child_count] = 1;
175         _curr_event = _last_event = curr_row;
177         // collapse if we're leaving a branch
178         if (_curr_event_parent && _connected) {
179             (*_callback_connections)[CALLB_COLLAPSE].block();
180             _event_list_view->collapse_row(_event_list_store->get_path(_curr_event_parent));
181             (*_callback_connections)[CALLB_COLLAPSE].block(false);
182         }
184         _curr_event_parent = (iterator)(NULL);
185     }      
187     _curr_event = _last_event = curr_row;
189     curr_row[_columns.event] = log;
190     curr_row[_columns.type] = event_type;
191     curr_row[_columns.description] = log->description;
193     // update the view
194     if (_connected) {
195         Gtk::TreePath curr_path = _event_list_store->get_path(_curr_event);
197         (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
198         (*_callback_connections)[CALLB_EXPAND].block();
200         _event_list_view->expand_to_path(curr_path);
201         _event_list_selection->select(curr_path);
202         _event_list_view->scroll_to_row(curr_path);
204         (*_callback_connections)[CALLB_EXPAND].block(false);
205         (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
206     }
208     updateUndoVerbs();
211 void
212 EventLog::notifyClearUndoEvent()
214     _clearUndo();    
215     updateUndoVerbs();
218 void
219 EventLog::notifyClearRedoEvent()
221     _clearRedo();
222     updateUndoVerbs();
225 void 
226 EventLog::connectWithDialog(Gtk::TreeView *event_list_view, CallbackMap *callback_connections)
228     _event_list_view = event_list_view;
229     _event_list_selection = event_list_view->get_selection();
230     _event_list_selection->set_mode(Gtk::SELECTION_SINGLE);
232     _callback_connections = callback_connections;
234     (*_callback_connections)[CALLB_SELECTION_CHANGE].block();
235     (*_callback_connections)[CALLB_EXPAND].block();
237     _event_list_view->expand_to_path(_event_list_store->get_path(_curr_event));
238     _event_list_selection->select(_curr_event);
240     (*_callback_connections)[CALLB_EXPAND].block(false);
241     (*_callback_connections)[CALLB_SELECTION_CHANGE].block(false);
243     _connected = true;
246 void
247 EventLog::updateUndoVerbs()
249     if(_document) {
251         if(_getUndoEvent()) { 
252             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, true);
254             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, String::ucompose("%1: %2", 
255                       Glib::ustring(_("_Undo")),
256                       Glib::ustring((*_getUndoEvent())[_columns.description])));
257         } else {
258             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->name(_document, _("_Undo"));
259             Inkscape::Verb::get(SP_VERB_EDIT_UNDO)->sensitive(_document, false);
260         }
262         if(_getRedoEvent()) {
263             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, true);
264             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, String::ucompose("%1: %2", 
265                       Glib::ustring(_("_Redo")),
266                       Glib::ustring((*_getRedoEvent())[_columns.description])));
268         } else {
269             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->name(_document, _("_Redo"));
270             Inkscape::Verb::get(SP_VERB_EDIT_REDO)->sensitive(_document, false);
271         }
273     }
278 EventLog::const_iterator
279 EventLog::_getUndoEvent() const
281     const_iterator undo_event = (const_iterator)NULL;
282     if( _curr_event != _event_list_store->children().begin() )
283         undo_event = _curr_event;
284     return undo_event;
287 EventLog::const_iterator
288 EventLog::_getRedoEvent() const
290     const_iterator redo_event = (const_iterator)NULL;
292     if ( _curr_event != _last_event ) {
294         if ( !_curr_event->children().empty() )
295             redo_event = _curr_event->children().begin();
296         else  {
297             redo_event = _curr_event;
298             ++redo_event;
300             if ( redo_event->parent() &&
301                  redo_event == redo_event->parent()->children().end() ) {
303                 redo_event = redo_event->parent();
304                 ++redo_event;
306             }
307         }
309     }
311     return redo_event;
314 void
315 EventLog::_clearUndo()
317     // TODO: Implement when needed
320 void
321 EventLog::_clearRedo()
323     if ( _last_event != _curr_event ) {
325         _last_event = _curr_event;
327         if ( !_last_event->children().empty() ) {
328             _last_event = _last_event->children().begin();
329         } else {
330             ++_last_event;
331         }
333         while ( _last_event != _event_list_store->children().end() ) {
335             if (_last_event->parent()) {
336                 while ( _last_event != _last_event->parent()->children().end() ) {
337                     _last_event = _event_list_store->erase(_last_event);
338                 }
339                 _last_event = _last_event->parent();
341                 (*_last_event)[_columns.child_count] = _last_event->children().size() + 1;
343                 ++_last_event;
344             } else {
345                 _last_event = _event_list_store->erase(_last_event);
346             }
348         }
350     }
353 } // namespace Inkscape
356 /*
357   Local Variables:
358   mode:c++
359   c-file-style:"stroustrup"
360   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
361   indent-tabs-mode:nil
362   fill-column:99
363   End:
364 */
365 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :