diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 16:29:01 +0000 |
commit | 35a96bde514a8897f6f0fcc41c5833bf63df2e2a (patch) | |
tree | 657d15a03cc46bd099fc2c6546a7a4ad43815d9f /src/composite-undo-stack-observer.cpp | |
parent | Initial commit. (diff) | |
download | inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.tar.xz inkscape-35a96bde514a8897f6f0fcc41c5833bf63df2e2a.zip |
Adding upstream version 1.0.2.upstream/1.0.2upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/composite-undo-stack-observer.cpp')
-rw-r--r-- | src/composite-undo-stack-observer.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/composite-undo-stack-observer.cpp b/src/composite-undo-stack-observer.cpp new file mode 100644 index 0000000..ce272b2 --- /dev/null +++ b/src/composite-undo-stack-observer.cpp @@ -0,0 +1,166 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Heavily inspired by Inkscape::XML::CompositeNodeObserver. + * + * Authors: + * David Yip <yipdw@rose-hulman.edu> + * + * Copyright (c) 2005 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <algorithm> + +#include "composite-undo-stack-observer.h" +#include "xml/event.h" + +namespace Inkscape { + +CompositeUndoStackObserver::CompositeUndoStackObserver() : _iterating(0) { } +CompositeUndoStackObserver::~CompositeUndoStackObserver() = default; + +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(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(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(Event* log) +{ + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueUndoCommit(log); + } + } + this->_unlock(); +} + +void +CompositeUndoStackObserver::notifyClearUndoEvent() +{ + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueClearUndo(); + } + } + this->_unlock(); +} + +void +CompositeUndoStackObserver::notifyClearRedoEvent() +{ + this->_lock(); + for(UndoObserverRecordList::iterator i = this->_active.begin(); i != _active.end(); ++i) { + if (!i->to_remove) { + i->issueClearRedo(); + } + } + 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(); ) { + if (i->to_remove) { + i = this->_active.erase(i); + } + else{ + ++i; + } + } + + i = this->_pending.begin(); + for(; i != this->_pending.begin(); ) { + if (i->to_remove) { + i = this->_active.erase(i); + } + else { + ++i; + } + } + + // Merge pending and active + this->_active.insert(this->_active.end(), this->_pending.begin(), this->_pending.end()); + this->_pending.clear(); + } +} + +} |