Refactor UndoRedoAction out of OpenRocketDocument and move into gui packages. Added interface UndoRedoListener so the OpenRocketDocument can send notification to the Undo/Redo buttons when the state of the undo stack changes.

This commit is contained in:
Kevin Ruland 2011-12-21 16:23:47 +00:00
parent 4194479d0c
commit 1b309dd786
5 changed files with 142 additions and 114 deletions

View File

@ -1,18 +1,12 @@
package net.sf.openrocket.document;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import javax.swing.AbstractAction;
import javax.swing.Action;
import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.document.events.SimulationChangeEvent;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.logging.TraceException;
import net.sf.openrocket.rocketcomponent.ComponentChangeEvent;
@ -21,7 +15,6 @@ import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.ArrayList;
import net.sf.openrocket.util.BugException;
/**
* Class describing an entire OpenRocket document, including a rocket and
@ -37,7 +30,6 @@ import net.sf.openrocket.util.BugException;
*/
public class OpenRocketDocument implements ComponentChangeListener {
private static final LogHelper log = Application.getLogger();
private static final Translator trans = Application.getTranslator();
/**
* The minimum number of undo levels that are stored.
@ -54,8 +46,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
/** Whether an undo error has already been reported to the user */
private static boolean undoErrorReported = false;
private final Rocket rocket;
private final Configuration configuration;
@ -72,7 +62,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
*/
private LinkedList<Rocket> undoHistory = new LinkedList<Rocket>();
private LinkedList<String> undoDescription = new LinkedList<String>();
/**
* The position in the undoHistory we are currently at. If modifications have been
* made to the rocket, the rocket is in "dirty" state and this points to the previous
@ -87,6 +77,8 @@ public class OpenRocketDocument implements ComponentChangeListener {
private String storedDescription = null;
private ArrayList<UndoRedoListener> undoRedoListeners = new ArrayList<UndoRedoListener>(2);
private File file = null;
private int savedID = -1;
@ -96,11 +88,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
private final List<DocumentChangeListener> listeners =
new ArrayList<DocumentChangeListener>();
/* These must be initialized after undo history is set up. */
private final UndoRedoAction undoAction;
private final UndoRedoAction redoAction;
public OpenRocketDocument(Rocket rocket) {
this(rocket.getDefaultConfiguration());
}
@ -112,9 +99,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
clearUndo();
undoAction = new UndoRedoAction(UndoRedoAction.UNDO);
redoAction = new UndoRedoAction(UndoRedoAction.REDO);
rocket.addComponentChangeListener(this);
}
@ -322,16 +306,6 @@ public class OpenRocketDocument implements ComponentChangeListener {
}
public Action getUndoAction() {
return undoAction;
}
public Action getRedoAction() {
return redoAction;
}
/**
* Clear the undo history.
*/
@ -343,11 +317,8 @@ public class OpenRocketDocument implements ComponentChangeListener {
undoHistory.add(rocket.copyWithOriginalID());
undoDescription.add(null);
undoPosition = 0;
if (undoAction != null)
undoAction.setAllValues();
if (redoAction != null)
redoAction.setAllValues();
fireUndoRedoChangeEvent();
}
@ -370,8 +341,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
undoDescription.set(undoPosition, nextDescription);
}
undoAction.setAllValues();
redoAction.setAllValues();
fireUndoRedoChangeEvent();
}
@ -430,8 +400,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
" undoHistory.size=" + undoHistory.size() + " isClean=" + isCleanState());
if (!isUndoAvailable()) {
logUndoError("Undo not available");
undoAction.setAllValues();
redoAction.setAllValues();
fireUndoRedoChangeEvent();
return;
}
if (storedDescription != null) {
@ -468,8 +437,7 @@ public class OpenRocketDocument implements ComponentChangeListener {
" undoHistory.size=" + undoHistory.size() + " isClean=" + isCleanState());
if (!isRedoAvailable()) {
logUndoError("Redo not available");
undoAction.setAllValues();
redoAction.setAllValues();
fireUndoRedoChangeEvent();
return;
}
if (storedDescription != null) {
@ -526,6 +494,22 @@ public class OpenRocketDocument implements ComponentChangeListener {
/////// Listeners
public void addUndoRedoListener( UndoRedoListener listener ) {
undoRedoListeners.add(listener);
}
public void removeUndoRedoListener( UndoRedoListener listener ) {
undoRedoListeners.remove(listener);
}
private void fireUndoRedoChangeEvent() {
UndoRedoListener[] array = undoRedoListeners.toArray(new UndoRedoListener[0]);
for (UndoRedoListener l : array) {
l.setAllValues();
}
}
public void addDocumentChangeListener(DocumentChangeListener listener) {
listeners.add(listener);
}
@ -544,73 +528,4 @@ public class OpenRocketDocument implements ComponentChangeListener {
/**
* Inner class to implement undo/redo actions.
*/
private class UndoRedoAction extends AbstractAction {
public static final int UNDO = 1;
public static final int REDO = 2;
private final int type;
// Sole constructor
public UndoRedoAction(int type) {
if (type != UNDO && type != REDO) {
throw new IllegalArgumentException("Unknown type = " + type);
}
this.type = type;
setAllValues();
}
// Actual action to make
@Override
public void actionPerformed(ActionEvent e) {
switch (type) {
case UNDO:
log.user("Performing undo, event=" + e);
undo();
break;
case REDO:
log.user("Performing redo, event=" + e);
redo();
break;
}
}
// Set all the values correctly (name and enabled/disabled status)
public void setAllValues() {
String name, desc;
boolean actionEnabled;
switch (type) {
case UNDO:
//// Undo
name = trans.get("OpenRocketDocument.Undo");
desc = getUndoDescription();
actionEnabled = isUndoAvailable();
this.putValue(SMALL_ICON, Icons.EDIT_UNDO);
break;
case REDO:
////Redo
name = trans.get("OpenRocketDocument.Redo");
desc = getRedoDescription();
actionEnabled = isRedoAvailable();
this.putValue(SMALL_ICON, Icons.EDIT_REDO);
break;
default:
throw new BugException("illegal type=" + type);
}
if (desc != null)
name = name + " (" + desc + ")";
putValue(NAME, name);
setEnabled(actionEnabled);
}
}
}

View File

@ -0,0 +1,8 @@
package net.sf.openrocket.document;
import java.util.EventListener;
public interface UndoRedoListener extends EventListener {
public void setAllValues();
}

View File

@ -554,7 +554,7 @@ public class BasicFrame extends JFrame {
menubar.add(menu);
Action action = document.getUndoAction();
Action action = UndoRedoAction.newUndoAction(document);
item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Z, ActionEvent.CTRL_MASK));
item.setMnemonic(KeyEvent.VK_U);
@ -562,8 +562,8 @@ public class BasicFrame extends JFrame {
item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.edit.undo.desc"));
menu.add(item);
action = document.getRedoAction();
action = UndoRedoAction.newRedoAction(document);
item = new JMenuItem(action);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Y, ActionEvent.CTRL_MASK));
item.setMnemonic(KeyEvent.VK_R);

View File

@ -0,0 +1,104 @@
package net.sf.openrocket.gui.main;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.UndoRedoListener;
import net.sf.openrocket.gui.util.Icons;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
/**
* Inner class to implement undo/redo actions.
*/
public class UndoRedoAction extends AbstractAction implements UndoRedoListener {
// Use Factory mechanism because we want to register the new instance as an
// UndoRedoListener.
public static UndoRedoAction newUndoAction( OpenRocketDocument document ) {
UndoRedoAction undo = new UndoRedoAction( UNDO, document );
document.addUndoRedoListener(undo);
return undo;
}
public static UndoRedoAction newRedoAction( OpenRocketDocument document ) {
UndoRedoAction redo = new UndoRedoAction( REDO, document );
document.addUndoRedoListener(redo);
return redo;
}
private static final LogHelper log = Application.getLogger();
private static final Translator trans = Application.getTranslator();
private static final int UNDO = 1;
private static final int REDO = 2;
private final int type;
private final OpenRocketDocument document;
// Sole constructor
private UndoRedoAction(int type, OpenRocketDocument document) {
this.document = document;
if (type != UNDO && type != REDO) {
throw new IllegalArgumentException("Unknown type = " + type);
}
this.type = type;
setAllValues();
}
// Actual action to make
@Override
public void actionPerformed(ActionEvent e) {
switch (type) {
case UNDO:
log.user("Performing undo, event=" + e);
document.undo();
break;
case REDO:
log.user("Performing redo, event=" + e);
document.redo();
break;
}
}
// Set all the values correctly (name and enabled/disabled status)
public void setAllValues() {
String name, desc;
boolean actionEnabled;
switch (type) {
case UNDO:
//// Undo
name = trans.get("OpenRocketDocument.Undo");
desc = document.getUndoDescription();
actionEnabled = document.isUndoAvailable();
this.putValue(SMALL_ICON, Icons.EDIT_UNDO);
break;
case REDO:
////Redo
name = trans.get("OpenRocketDocument.Redo");
desc = document.getRedoDescription();
actionEnabled = document.isRedoAvailable();
this.putValue(SMALL_ICON, Icons.EDIT_REDO);
break;
default:
throw new BugException("illegal type=" + type);
}
if (desc != null)
name = name + " (" + desc + ")";
putValue(NAME, name);
setEnabled(actionEnabled);
}
}

View File

@ -21,6 +21,7 @@ import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.file.GeneralRocketLoader;
import net.sf.openrocket.file.RocketLoadException;
import net.sf.openrocket.file.motor.GeneralMotorLoader;
import net.sf.openrocket.gui.main.UndoRedoAction;
import net.sf.openrocket.l10n.ResourceBundleTranslator;
import net.sf.openrocket.masscalc.BasicMassCalculator;
import net.sf.openrocket.masscalc.MassCalculator;
@ -96,8 +97,8 @@ public class IntegrationTest extends BaseTestCase {
document = loader.load(is);
is.close();
undoAction = document.getUndoAction();
redoAction = document.getRedoAction();
undoAction = UndoRedoAction.newUndoAction(document );
redoAction = UndoRedoAction.newRedoAction(document);
config = document.getSimulation(0).getConfiguration();
conditions = new FlightConditions(config);