Logo Search packages:      
Sourcecode: inkscape version File versions  Download package

composite-undo-stack-observer.cpp

/**
 * 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 {

00020 CompositeUndoStackObserver::CompositeUndoStackObserver() : _iterating(0) { }
CompositeUndoStackObserver::~CompositeUndoStackObserver() { }

void
00024 CompositeUndoStackObserver::add(UndoStackObserver& observer)
{
      if (!this->_iterating) {
            this->_active.push_back(UndoStackObserverRecord(observer));
      } else {
            this->_pending.push_back(UndoStackObserverRecord(observer));
      }
}

void
00034 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
00045 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
00057 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
00070 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();
      }
}

}

Generated by  Doxygen 1.6.0   Back to index