/****************************************************************************** * Copyright: GPL v3 * * * * 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/>. * ******************************************************************************/ package dbaCore.data; import dbaCore.data.events.Change; import dbaCore.data.events.ChangeListener; import dbaCore.data.events.Time; import java.util.ArrayList; /** * Class representing a Undo/Redo History * * @author Sebastian Theuermann */ public final class History extends HistoricObject { private ArrayList<HistoricObject> history; private HistoricObject currentElement; public History() { super(); history = new ArrayList<>(); } public History(HistoricObject historicElement) { this(); initialize(historicElement); } /** * (Re-)Initializes the History * * @param currentElement the Database that is current in use */ public void initialize(HistoricObject currentElement) { history.clear(); this.currentElement = currentElement; // disconnect redundant listener disconnectChangeListener(); history.add(currentElement); super.changeListener = new ChangeListener() { @Override public void Change(Change change) { switch (change.getTime()) { case BEFORECHANGE: purgeFuture(); makeHistory(); notifyOfCurrentElementChange(); break; case AFTERCHANGE: changeSupport.fireChange(change.getTime()); break; } } }; connectChangeListener(); } /** * Moves forward in history */ public boolean travelForward() { boolean success = false; disconnectChangeListener(); if (getForwardPossible()) { currentElement = history.get(history.indexOf(currentElement) + 1); success = true; } connectChangeListener(); notifyOfCurrentElementChange(); return success; } /** * Moves backward in history */ public boolean travelBackward() { boolean success = false; disconnectChangeListener(); if (getBackwardPossible()) { currentElement = history.get(history.indexOf(currentElement) - 1); success = true; } connectChangeListener(); notifyOfCurrentElementChange(); return success; } /** * Adds a PropertyChangedListener to the currentDatabase */ private void connectChangeListener() { currentElement.addChangeListener(changeListener); } /** * Removes the PropertyChangedListener from the currentDatabase */ private void disconnectChangeListener() { currentElement.removeChangeListener(changeListener); } /** * Removes all future-Versions of the currentDatabase */ private void purgeFuture() { int futureDbCount = history.size() - 1 - history.indexOf(currentElement); for (int i = 0; i < futureDbCount; i++) { history.remove(history.size() - 1); } } /** * Adds the current Database to the history */ private void makeHistory() { makeHistory((HistoricObject) currentElement.getClone()); } /** * Adds a Database to the history * * @param oldElement the old element to add to the history */ private void makeHistory(HistoricObject oldElement) { history.set(history.indexOf(currentElement), oldElement); history.add(currentElement); setDirty(true); } /** * Returns if you can navigate backward in history * * @return true if backward is possible, false if not */ public boolean getBackwardPossible() { return !history.isEmpty() && history.indexOf(currentElement) != 0; } /** * Returns if you can navigate forward in history * * @return true ==> forward possible, false ==> forward impossible */ public boolean getForwardPossible() { return !history.isEmpty() && (history.indexOf(currentElement) < (history.size() - 1)); } /** * Adds a Element at the current index and erases all elements past * that index * * @param newObject the element to add to the History */ public void addHistoricObject(HistoricObject newObject) { purgeFuture(); makeHistory((HistoricObject) currentElement.getClone()); // Replace currentElement with new one history.remove(currentElement); currentElement = newObject; history.add(currentElement); connectChangeListener(); notifyOfCurrentElementChange(); } /** * Returns the Database that is currently active * * @return the current Element */ public HistoricObject getCurrentElement() { return currentElement; } /** * Returns the whole History * * @return the whole History */ public ArrayList<HistoricObject> getHistory() { return history; } private void notifyOfCurrentElementChange() { // Notify listeners that currentDatabase has changed changeSupport.fireChange(Time.AFTERCHANGE); } @Override public Object getClone() { return null; } }