diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/composite-undo-stack-observer.cpp | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/composite-undo-stack-observer.cpp')
| -rw-r--r-- | src/composite-undo-stack-observer.cpp | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/composite-undo-stack-observer.cpp b/src/composite-undo-stack-observer.cpp new file mode 100644 index 000000000..04890711b --- /dev/null +++ b/src/composite-undo-stack-observer.cpp @@ -0,0 +1,136 @@ +/** + * Aggregates undo stack observers for convenient management and triggering in SPDocument + * + * Heavily inspired by Inkscape::XML::CompositeNodeObserver. + * + * Authors: + * David Yip <yipdw@rose-hulman.edu> + * + * Copyright (c) 2005 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + + +#include "composite-undo-stack-observer.h" +#include "xml/event.h" + +namespace Inkscape { + +CompositeUndoStackObserver::CompositeUndoStackObserver() : _iterating(0) { } +CompositeUndoStackObserver::~CompositeUndoStackObserver() { } + +void +CompositeUndoStackObserver::add(UndoStackObserver& observer) +{ + if (!this->_iterating) { + this->_active.push_back(UndoStackObserverRecord(observer)); + } else { + this->_pending.push_back(UndoStackObserverRecord(observer)); + } +} + +void +CompositeUndoStackObserver::remove(UndoStackObserver& observer) +{ + if (!this->_iterating) { + // logical-or operator short-circuits + this->_remove_one(this->_active, observer) || this->_remove_one(this->_pending, observer); + } else { + this->_mark_one(this->_active, observer) || this->_mark_one(this->_pending, observer); + } +} + +void +CompositeUndoStackObserver::notifyUndoEvent(XML::Event* log) +{ + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueUndo(log); + } + } + this->_unlock(); +} + +void +CompositeUndoStackObserver::notifyRedoEvent(XML::Event* log) +{ + + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueRedo(log); + } + } + this->_unlock(); +} + +void +CompositeUndoStackObserver::notifyUndoCommitEvent(XML::Event* log) +{ + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueUndoCommit(log); + } + } + this->_unlock(); +} + +bool +CompositeUndoStackObserver::_remove_one(UndoObserverRecordList& list, UndoStackObserver& o) +{ + UndoStackObserverRecord eq_comp(o); + + UndoObserverRecordList::iterator i = std::find_if(list.begin(), list.end(), std::bind1st(std::equal_to< UndoStackObserverRecord >(), eq_comp)); + + if (i != list.end()) { + list.erase(i); + return true; + } else { + return false; + } +} + +bool +CompositeUndoStackObserver::_mark_one(UndoObserverRecordList& list, UndoStackObserver& o) +{ + UndoStackObserverRecord eq_comp(o); + + UndoObserverRecordList::iterator i = std::find_if(list.begin(), list.end(), std::bind1st(std::equal_to< UndoStackObserverRecord >(), eq_comp)); + + if (i != list.end()) { + (*i).to_remove = true; + return true; + } else { + return false; + } +} + +void +CompositeUndoStackObserver::_unlock() +{ + if (!--this->_iterating) { + // Remove marked observers + UndoObserverRecordList::iterator i = this->_active.begin(); + for(; i != this->_active.begin(); i++) { + if (i->to_remove) { + this->_active.erase(i); + } + } + + i = this->_pending.begin(); + for(; i != this->_pending.begin(); i++) { + if (i->to_remove) { + this->_active.erase(i); + } + } + + // Merge pending and active + this->_active.insert(this->_active.end(), this->_pending.begin(), this->_pending.end()); + this->_pending.clear(); + } +} + +} |
