/*******************************************************************************
* Copyright (c) 2013 Bundlemaker project team.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bundlemaker project team - initial API and implementation
******************************************************************************/
package org.bundlemaker.core.common.history;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
/**
* A "add-only" history of things, that can be browsed forward and backward
*
* @author Nils Hartmann (nils@nilshartmann.net)
*
*/
public abstract class History<T> {
private final List<IHistoryChangedListener<T>> _listeners = new LinkedList<IHistoryChangedListener<T>>();
private final List<T> _objects = new LinkedList<T>();
private final Stack<Integer> _backStack = new Stack<Integer>();
private final Stack<Integer> _forwardStack = new Stack<Integer>();
/**
* The current object index. The index is not contained in back or forward stack
*/
private int _currentObject = -1;
public void add(T t) {
if (t == null) {
return;
}
if (_currentObject != -1) {
_backStack.push(_currentObject);
}
_objects.add(t);
_currentObject = _objects.size() - 1;
while (!_forwardStack.isEmpty()) {
_backStack.add(0, _forwardStack.pop());
}
fireHistoryChangedListener();
}
public boolean canGoBack() {
return _backStack.size() > 0;
}
public void goBack() {
if (!canGoBack()) {
throw new IllegalStateException("Cannot move Back: already at first position in history");
}
if (_currentObject != -1) {
_forwardStack.add(_currentObject);
}
Integer newItem = _backStack.pop();
_currentObject = newItem;
fireHistoryChangedListener();
}
public boolean canGoForward() {
return !_forwardStack.isEmpty();
}
public void dumpHistory() {
System.out.println("CURRENT OBJECT: " + _currentObject);
System.out.println("BACK STACK:");
for (int i = 0; i < _backStack.size(); i++) {
System.out.printf("%d (%s)%n", _backStack.get(i), _objects.get(_backStack.get(i)));
}
System.out.println("FORWARD STACK:");
for (int i = 0; i < _forwardStack.size(); i++) {
System.out.printf("%d (%s)%n", _forwardStack.get(i), _objects.get(_forwardStack.get(i)));
}
// for (int i = 0; i < _history.size(); i++) {
// System.out.printf("[%d %s] -> %d (%s)%n", i, (i == _currentItem ? "*" : ""), _history.get(i),
// _objects.get(_history.get(i)));
// }
}
public void goForward() {
if (!canGoForward()) {
throw new IllegalStateException("Cannot move forward in history: already at last position");
}
if (_currentObject != -1) {
_backStack.add(_currentObject);
}
Integer newItem = _forwardStack.pop();
System.out.println(" -> New Item after pop: " + newItem);
_currentObject = newItem;
fireHistoryChangedListener();
}
/**
* @return
*/
public T getCurrent() {
T item = _objects.get(_currentObject);
return item;
}
protected void fireHistoryChangedListener() {
for (IHistoryChangedListener<T> listener : _listeners) {
listener.historyChanged(this);
}
}
public void addHistoryChangedListener(IHistoryChangedListener<T> listener) {
if (listener != null && !_listeners.contains(listener)) {
_listeners.add(listener);
}
}
public void removeHistoryChangedListener(IHistoryChangedListener<T> listener) {
if (listener != null) {
_listeners.remove(listener);
}
}
}