package org.activityinfo.ui.client.widget.undo;
/*
* #%L
* ActivityInfo Server
* %%
* Copyright (C) 2009 - 2013 UNICEF
* %%
* This program 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.
*
* This program 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 this program. If not, see
* <http://www.gnu.org/licenses/gpl-3.0.html>.
* #L%
*/
import com.google.common.collect.Lists;
import java.util.List;
/**
* @author yuriyz on 2/17/14.
*/
public class UndoManager {
private final List<IsUndoable> undoables = Lists.newArrayList();
private final List<UndoListener> listeners = Lists.newArrayList();
private int position = -1;
public UndoManager() {
}
public void addUndoable(IsUndoable undoable) {
if (undoable != null) {
position++;
undoables.add(position, undoable);
removeUndoablesFrom(position);
fireCreatedEvent(new UndoableCreatedEvent(undoable));
}
}
/**
* Removes undoables from list start from position but excluding this position itself.
*
* @param position position from which undoables will be removed but excluding this position itself
*/
private void removeUndoablesFrom(int position) {
for (int i = position + 1; i < undoables.size(); i++) {
undoables.remove(i);
}
}
private IsUndoable getUndoAtPosition() {
return getUndoableAtPosition(position);
}
private IsUndoable getRedoAtPosition() {
return getUndoableAtPosition(position + 1);
}
private IsUndoable getUndoableAtPosition(int position) {
if (position < 0 || position >= undoables.size()) {
return null;
}
return undoables.get(position);
}
public void undo() {
final IsUndoable undoable = getUndoAtPosition();
if (undoable != null) {
position--;
undoable.undo();
fireExecutedEvent(new UndoableExecutedEvent(undoable));
}
}
public boolean canUndo() {
return getUndoAtPosition() != null;
}
public boolean canRedo() {
return getRedoAtPosition() != null;
}
public void redo() {
final IsUndoable undoable = getRedoAtPosition();
if (undoable != null) {
position++;
undoable.redo();
fireExecutedEvent(new UndoableExecutedEvent(undoable));
}
}
private void fireExecutedEvent(UndoableExecutedEvent undoEvent) {
for (UndoListener listener : listeners) {
listener.onUndoableExecuted(undoEvent);
}
}
private void fireCreatedEvent(UndoableCreatedEvent undoEvent) {
for (UndoListener listener : listeners) {
listener.onUndoableCreated(undoEvent);
}
}
public void addListener(UndoListener listener) {
listeners.add(listener);
}
public void removeListener(UndoListener listener) {
listeners.remove(listener);
}
}