package pipe.historyActions; import uk.ac.imperial.pipe.models.petrinet.Transition; import java.util.ArrayList; import java.util.List; import java.util.Observable; /** * AnimationHistory for an individual PetriNet */ public final class AnimationHistoryImpl extends Observable implements AnimationHistory { /** * List to hold transitions fired in their order * Used for going back/forward in time */ private List<Transition> firingSequence = new ArrayList<>(); /** * Current index of the firingSequence; * Initialised to -1 so when the first item is added it points to zero */ private int currentPosition = -1; /** * Cannot step forward if head of the list * * @return true if stepping forward within the animation is allowed, that is if there are transition firings to redo */ @Override public boolean isStepForwardAllowed() { return currentPosition < firingSequence.size() - 1; } /** * Can step back if currentPosition points to any transitions * * @return true if stepping backward within the animation is allowed, that is if there are transition firings to undo */ @Override public boolean isStepBackAllowed() { return currentPosition >= 0; } /** * Steps forward firing the transition associated with the latest action */ @Override public void stepForward() { if (isStepForwardAllowed()) { currentPosition++; flagChanged(); } } /** * Steps backwards updating the current transition highlighted in the list */ @Override public void stepBackwards() { if (isStepBackAllowed()) { currentPosition--; flagChanged(); } } /** * Remove all steps past the current step */ @Override public void clearStepsForward() { if (currentPosition >= -1 && currentPosition + 1 < firingSequence.size()) { while (firingSequence.size() > currentPosition + 1) { firingSequence.remove(firingSequence.size() - 1); } } } /** * * @return list of transitions in the firing sequence */ @Override public List<Transition> getFiringSequence() { return firingSequence; } /** * * @return current position in the firing sequence */ @Override public int getCurrentPosition() { return currentPosition; } /** * Add a transition to the head of the firing sequence * @param transition to be added */ @Override public void addHistoryItem(Transition transition) { firingSequence.add(transition); currentPosition++; flagChanged(); } /** * * @return transition at current position in the firing sequence */ @Override public Transition getCurrentTransition() { if (currentPosition >= 0) { return firingSequence.get(currentPosition); } throw new RuntimeException("No transitions in history"); } /** * * @param index of the transition * @return transition at the given index in the firing sequence */ @Override public Transition getTransition(int index) { if (index <= firingSequence.size()) { return firingSequence.get(index); } throw new RuntimeException("Index is greater than number of transitions stored"); } /** * Clears the firing sequence */ @Override public void clear() { currentPosition = -1; firingSequence.clear(); flagChanged(); } /** * Rolls the setting changed and notifying observers into one method call. * It tells Observers that it has changed */ private void flagChanged() { setChanged(); notifyObservers(); } }