// PathVisio, // a tool for data visualization and analysis using Biological Pathways // Copyright 2006-2011 BiGCaT Bioinformatics // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // package org.pathvisio.core.view; import java.util.ArrayList; import java.util.List; import org.pathvisio.core.Engine; import org.pathvisio.core.model.Pathway; /** Manages a stack of undo actions */ public class UndoManager { public static final String CANT_UNDO = "Can't undo"; private List undoList = new ArrayList(); private Pathway pathway; public void setPathway (Pathway pathway) { this.pathway = pathway; } private Engine engine; /** * Check if this undo manager is active. * If there is no instance of Engine available, * the undo manager will not record any undo events. * Provide an instance of engine to activate the undo * manager. * @see #activate(Engine) */ public boolean isActive() { return engine != null; } /** * Set the engine for this undo manager. * @param engine */ public void activate (Engine engine) { this.engine = engine; } /** * Get the engine for this undo manager. The engine * can be null, in which case the undo manager will be * inactive. * @return The Engine, or null if the undo manager is inactive. */ protected Engine getEngine() { return engine; } static final int MAX_UNDO_SIZE = 25; /** Insert a new action into the Undo Queue based on an UndoAction object that already contains a copy of the original state of the pathway. This way you can actually record the action after the pathway has already modified, useful for collapsing multiple drag events into one action. @param act: UndoAction containing pre-recorded pathway state and description of the action. */ public void newAction (UndoAction act) { if(!isActive()) return; //Don' record event if inactive act.setUndoManager(this); undoList.add (act); if (undoList.size() > MAX_UNDO_SIZE) { undoList.remove(0); } fireUndoManagerEvent (new UndoManagerEvent (getTopMessage())); } /** Insert a new action into the Undo Queue. This method will make a copy of the current state of the pathway, so call this method before the action actually takes place. @param desc: description of the change, for display in the edit menu. */ public void newAction (String desc) { if(!isActive()) return; //Don' record event if inactive if(pathway != null) { UndoAction x = new UndoAction (desc, (Pathway)pathway.clone()); x.setUndoManager(this); newAction (x); } } public String getTopMessage() { String result; if (undoList.size() == 0) { result = CANT_UNDO; } else { result = undoList.get(undoList.size() - 1).getMessage(); } return result; } void undo() { if (undoList.size() > 0 && isActive()) { UndoAction a = undoList.get(undoList.size()-1); a.undo(); undoList.remove(a); fireUndoManagerEvent (new UndoManagerEvent (getTopMessage())); } } private List listeners = new ArrayList (); public void addListener (UndoManagerListener v) { listeners.add(v); } public void removeListener (UndoManagerListener v) { listeners.remove(v); } /** This is called whenever a new item is added to the Undo Manager, or when an undo action takes place. mainly intended for the menu item to update itself. */ void fireUndoManagerEvent (UndoManagerEvent e) { //printSummary(); for (UndoManagerListener g : listeners) { g.undoManagerEvent (e); } } private boolean disposed = false; public void dispose() { assert (!disposed); undoList.clear(); listeners.clear(); disposed = true; } /** debugging helper function */ @SuppressWarnings("unused") private void printSummary() { System.out.println ("==============================="); System.out.println (undoList.size() + " remaining"); for (int i = undoList.size() - 1; i >= 0; --i) { System.out.printf ("%3d: ", i); undoList.get(i).printSummary(); System.out.println (); } System.out.println ("Current pathway"); System.out.print (pathway.summary()); System.out.println(); } }