/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.draw.undo;
import java.util.LinkedList;
import com.cburch.logisim.util.EventSourceWeakSupport;
public class UndoLog {
private static final int MAX_UNDO_SIZE = 64;
private EventSourceWeakSupport<UndoLogListener> listeners;
private LinkedList<Action> undoLog;
private LinkedList<Action> redoLog;
private int modCount;
public UndoLog() {
this.listeners = new EventSourceWeakSupport<UndoLogListener>();
this.undoLog = new LinkedList<Action>();
this.redoLog = new LinkedList<Action>();
this.modCount = 0;
}
//
// listening methods
//
public void addProjectListener(UndoLogListener what) {
listeners.add(what);
}
public void clearModified() {
modCount = 0;
}
//
// mutator methods
//
public void doAction(Action act) {
if (act == null)
return;
act.doIt();
logAction(act);
}
private void fireEvent(int action, Action actionObject) {
UndoLogEvent e = null;
for (UndoLogListener listener : listeners) {
if (e == null)
e = new UndoLogEvent(this, action, actionObject);
listener.undoLogChanged(e);
}
}
public Action getRedoAction() {
if (redoLog.isEmpty()) {
return null;
} else {
return redoLog.getLast();
}
}
//
// accessor methods
//
public Action getUndoAction() {
if (undoLog.isEmpty()) {
return null;
} else {
return undoLog.getLast();
}
}
public boolean isModified() {
return modCount != 0;
}
public void logAction(Action act) {
redoLog.clear();
if (!undoLog.isEmpty()) {
Action prev = undoLog.getLast();
if (act.shouldAppendTo(prev)) {
if (prev.isModification())
--modCount;
Action joined = prev.append(act);
if (joined == null) {
fireEvent(UndoLogEvent.ACTION_DONE, act);
return;
}
act = joined;
}
while (undoLog.size() > MAX_UNDO_SIZE) {
undoLog.removeFirst();
}
}
undoLog.add(act);
if (act.isModification())
++modCount;
fireEvent(UndoLogEvent.ACTION_DONE, act);
}
public void redoAction() {
if (!redoLog.isEmpty()) {
Action action = redoLog.removeLast();
if (action.isModification())
++modCount;
action.doIt();
undoLog.add(action);
fireEvent(UndoLogEvent.ACTION_DONE, action);
}
}
public void removeProjectListener(UndoLogListener what) {
listeners.remove(what);
}
public void undoAction() {
if (!undoLog.isEmpty()) {
Action action = undoLog.removeLast();
if (action.isModification())
--modCount;
action.undo();
redoLog.add(action);
fireEvent(UndoLogEvent.ACTION_UNDONE, action);
}
}
}