/*
* Authors:
* David Yip <yipdw@rose-hulman.edu>
*
* Copyright (c) 2005 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifndef SEEN_COMPOSITE_UNDO_COMMIT_OBSERVER_H
#define SEEN_COMPOSITE_UNDO_COMMIT_OBSERVER_H
#include "inkgc/gc-alloc.h"
#include "undo-stack-observer.h"
#include <list>
namespace Inkscape {
struct Event;
/**
* Aggregates UndoStackObservers for management and triggering in an SPDocument's undo/redo
* system.
*
* Heavily inspired by Inkscape::XML::CompositeNodeObserver.
*/
class CompositeUndoStackObserver : public UndoStackObserver {
public:
/**
* Structure for tracking UndoStackObservers.
*/
struct UndoStackObserverRecord {
public:
/**
* Constructor.
*
* \param o Reference to the UndoStackObserver that this UndoStackObserverRecord
* will track.
*/
UndoStackObserverRecord(UndoStackObserver& o) : to_remove(false), _observer(o) { }
bool to_remove;
/**
* Overloaded equality test operator to facilitate usage of STL find algorithms.
*/
bool operator==(UndoStackObserverRecord const& _x) const
{
return &(this->_observer) == &(_x._observer);
}
/**
* Issue a redo event to the UndoStackObserver that is associated with this UndoStackObserverRecord.
*
* \param log The event log generated by the redo event.
*/
void issueRedo(Event* log)
{
this->_observer.notifyRedoEvent(log);
}
/**
* Issue an undo event to the UndoStackObserver that is associated with this
* UndoStackObserverRecord.
*
* \param log The event log generated by the undo event.
*/
void issueUndo(Event* log)
{
this->_observer.notifyUndoEvent(log);
}
/**
* Issues a committed event to the UndoStackObserver that is associated with this
* UndoStackObserverRecord.
*
* \param log The event log being committed to the undo stack.
*/
void issueUndoCommit(Event* log)
{
this->_observer.notifyUndoCommitEvent(log);
}
/**
* Issue a clear undo event to the UndoStackObserver
* that is associated with this
* UndoStackObserverRecord.
*/
void issueClearUndo()
{
this->_observer.notifyClearUndoEvent();
}
/**
* Issue a clear redo event to the UndoStackObserver
* that is associated with this
* UndoStackObserverRecord.
*/
void issueClearRedo()
{
this->_observer.notifyClearRedoEvent();
}
private:
UndoStackObserver& _observer;
};
/// A list of UndoStackObserverRecords, used to aggregate multiple UndoStackObservers.
typedef std::list< UndoStackObserverRecord, GC::Alloc< UndoStackObserverRecord, GC::MANUAL > > UndoObserverRecordList;
/**
* Constructor.
*/
CompositeUndoStackObserver();
virtual ~CompositeUndoStackObserver();
/**
* Add an UndoStackObserver.
*
* \param observer Reference to an UndoStackObserver to add.
*/
void add(UndoStackObserver& observer);
/**
* Remove an UndoStackObserver.
*
* \param observer Reference to an UndoStackObserver to remove.
*/
void remove(UndoStackObserver& observer);
/**
* Notify all registered UndoStackObservers of an undo event.
*
* \param log The event log generated by the undo event.
*/
void notifyUndoEvent(Event* log);
/**
* Notify all registered UndoStackObservers of a redo event.
*
* \param log The event log generated by the redo event.
*/
void notifyRedoEvent(Event* log);
/**
* Notify all registered UndoStackObservers of an event log being committed to the undo stack.
*
* \param log The event log being committed to the undo stack.
*/
void notifyUndoCommitEvent(Event* log);
virtual void notifyClearUndoEvent();
virtual void notifyClearRedoEvent();
private:
// Remove an observer from a given list
bool _remove_one(UndoObserverRecordList& list, UndoStackObserver& rec);
// Mark an observer for removal from a given list
bool _mark_one(UndoObserverRecordList& list, UndoStackObserver& rec);
// Keep track of whether or not we are notifying observers
unsigned int _iterating;
// Observers in the active list
UndoObserverRecordList _active;
// Observers to be added
UndoObserverRecordList _pending;
// Prevents the observer vector from modifications during
// iteration through the vector
void _lock() { this->_iterating++; }
void _unlock();
};
}
#endif // SEEN_COMPOSITE_UNDO_COMMIT_OBSERVER_H