[skycastle-commits] SF.net SVN: skycastle: [483] trunk/skycastle/modules

  • From: zzorn@xxxxxxxxxxxxxxxxxxxxx
  • To: skycastle-commits@xxxxxxxxxxxxx
  • Date: Sat, 26 Apr 2008 12:14:46 -0700

Revision: 483
          http://skycastle.svn.sourceforge.net/skycastle/?rev=483&view=rev
Author:   zzorn
Date:     2008-04-26 12:14:45 -0700 (Sat, 26 Apr 2008)

Log Message:
-----------
Implemented a CommandStack that enables running undoable commands, and which 
provides Undo and Redo Actions, as well as a practical overrideable 
CommandAction.

Modified Paths:
--------------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java

Added Paths:
-----------
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchToolbarFactory.java
    
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java
    trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/AbstractCommand.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/Command.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandAction.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStack.java
    
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
    trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/
    
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java

Removed Paths:
-------------
    trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java   
    2008-04-26 17:03:10 UTC (rev 482)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/Sketch3DUI.java   
    2008-04-26 19:14:45 UTC (rev 483)
@@ -179,8 +179,8 @@
 
     private JComponent createNorthPanel()
     {
-        SketchUi sketchUi = new SketchUi();
-        return sketchUi.createToolbar();
+        SketchToolbarFactory sketchFactory = new SketchToolbarFactory();
+        return sketchFactory.createToolbar();
     }
 
 

Copied: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchToolbarFactory.java
 (from rev 481, 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java)
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchToolbarFactory.java
                             (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchToolbarFactory.java
     2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,60 @@
+package org.skycastle.sketch;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+/**
+ * @author Hans Haggstrom
+ */
+public class SketchToolbarFactory
+{
+
+    public JToolBar createToolbar()
+    {
+        final JToolBar toolBar = new JToolBar();
+        toolBar.add( new JButton( new AbstractAction( "Quit" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+                System.exit( 0 );
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "New Page" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom Out" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom In" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+        toolBar.add( new JButton( new AbstractAction( "Zoom to show all" )
+        {
+
+            public void actionPerformed( final ActionEvent e )
+            {
+            }
+
+        } ) );
+
+        toolBar.setVisible( true );
+        return toolBar;
+    }
+}

Deleted: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java
===================================================================
--- trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java 
2008-04-26 17:03:10 UTC (rev 482)
+++ trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchUi.java 
2008-04-26 19:14:45 UTC (rev 483)
@@ -1,60 +0,0 @@
-package org.skycastle.sketch;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-
-/**
- * @author Hans Haggstrom
- */
-public class SketchUi
-{
-
-    public JToolBar createToolbar()
-    {
-        final JToolBar toolBar = new JToolBar();
-        toolBar.add( new JButton( new AbstractAction( "Quit" )
-        {
-
-            public void actionPerformed( final ActionEvent e )
-            {
-                System.exit( 0 );
-            }
-
-        } ) );
-        toolBar.add( new JButton( new AbstractAction( "New Page" )
-        {
-
-            public void actionPerformed( final ActionEvent e )
-            {
-            }
-
-        } ) );
-        toolBar.add( new JButton( new AbstractAction( "Zoom Out" )
-        {
-
-            public void actionPerformed( final ActionEvent e )
-            {
-            }
-
-        } ) );
-        toolBar.add( new JButton( new AbstractAction( "Zoom In" )
-        {
-
-            public void actionPerformed( final ActionEvent e )
-            {
-            }
-
-        } ) );
-        toolBar.add( new JButton( new AbstractAction( "Zoom to show all" )
-        {
-
-            public void actionPerformed( final ActionEvent e )
-            {
-            }
-
-        } ) );
-
-        toolBar.setVisible( true );
-        return toolBar;
-    }
-}

Added: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
                            (rev 0)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SketchView.java   
    2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,61 @@
+package org.skycastle.sketch;
+
+import org.skycastle.opengl.Canvas3D;
+import org.skycastle.util.simpleui.SimpleFrame;
+
+import javax.swing.*;
+import java.awt.BorderLayout;
+import java.awt.Component;
+
+/**
+ * A view, which presents the 3D view of the sketch, and provides input events.
+ *
+ * @author Hans Häggström
+ */
+// TODO: Have both a navigation stack and an undo stack, that are independent  
+public class SketchView
+{
+    private Component myUiComponent;
+    private Canvas3D myCanvas3D;
+    private JToolBar myToolBar;
+
+    /**
+     * Creates a new {@link org.skycastle.sketch.SketchView}.
+     */
+    public SketchView()
+    {
+
+        myCanvas3D = new Canvas3D();
+
+
+        final JPanel panel = new JPanel( new BorderLayout() );
+        panel.add( myCanvas3D.get3DView(), BorderLayout.CENTER );
+        myToolBar = new JToolBar();
+        panel.add( myToolBar, BorderLayout.NORTH );
+
+
+        new SimpleFrame( panel );
+
+/*
+        final StrokeRenderer strokeRenderer = new StrokeRenderer( 
createTestStroke() );
+        myCanvas3D.set3DNode( strokeRenderer );
+*/
+
+    }
+
+    /**
+     * An action / command in the application.
+     *
+     * @param action
+     */
+    void addAction( Action action )
+    {
+
+    }
+
+
+    public Component getUiComponent()
+    {
+        return myUiComponent;
+    }
+}

Modified: 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
===================================================================
--- 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
  2008-04-26 17:03:10 UTC (rev 482)
+++ 
trunk/skycastle/modules/ui/src/main/java/org/skycastle/sketch/SkycastleSketch.java
  2008-04-26 19:14:45 UTC (rev 483)
@@ -6,14 +6,11 @@
 import com.jme.scene.Spatial;
 import com.jme.scene.shape.Box;
 import com.jme.scene.state.LightState;
-import org.skycastle.opengl.Canvas3D;
 import org.skycastle.sketch.model.point.StrokePointImpl;
 import org.skycastle.sketch.model.stroke.Stroke;
 import org.skycastle.sketch.model.stroke.StrokeImpl;
 import org.skycastle.util.simpleui.SimpleFrame;
 
-import javax.swing.*;
-import java.awt.BorderLayout;
 import java.util.Random;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -53,21 +50,12 @@
         // This way the console output is a bit more relevant.
         LOGGER.setLevel( Level.WARNING );
 
+        final SketchView sketchView = new SketchView();
 
-        Canvas3D canvas3D = new Canvas3D();
+        // TODO: Register a model modifying input listener and navigating 
input listener to the view
 
-        SketchUi sketchUi = new SketchUi();
+        new SimpleFrame( sketchView.getUiComponent() );
 
-        JPanel panel = new JPanel( new BorderLayout() );
-        panel.add( canvas3D.get3DView(), BorderLayout.CENTER );
-        panel.add( sketchUi.createToolbar(), BorderLayout.NORTH );
-
-        new SimpleFrame( panel );
-
-
-        final StrokeRenderer strokeRenderer = new StrokeRenderer( 
createTestStroke() );
-        canvas3D.set3DNode( strokeRenderer );
-
 /*
         Sketch3DUI sketch3DUI = new Sketch3DUI();
         sketch3DUI.start();
@@ -82,8 +70,8 @@
     {
         final StrokeImpl stroke = new StrokeImpl();
 
-        float x = 0.0f;
-        float y = 0.0f;
+        float x = 0;
+        float y = 0;
         final Random random = new Random();
 
         for ( int i = 0; i < 1000; i++ )

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/AbstractCommand.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/AbstractCommand.java
                         (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/AbstractCommand.java
 2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,82 @@
+package org.skycastle.util.command;
+
+import org.skycastle.util.ParameterChecker;
+
+/**
+ * @author Hans Häggström
+ */
+public abstract class AbstractCommand
+        implements Command
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final String myDescription;
+    private final boolean myUndoable;
+    private final boolean myDisruptive;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new non-disruptive {@link AbstractCommand}.
+     *
+     * @param description an user readable description of this command.
+     * @param undoable    true if this is an undoable command.
+     */
+    public AbstractCommand( final String description, final boolean undoable )
+    {
+        this( description, undoable, false );
+    }
+
+
+    /**
+     * Creates a new {@link AbstractCommand}.
+     *
+     * @param description an user readable description of this command.
+     * @param undoable    true if this is an undoable command.
+     * @param disruptive  true if this command should clear the previous undo 
and redo stacks.
+     */
+    public AbstractCommand( final String description, final boolean undoable, 
final boolean disruptive )
+    {
+        ParameterChecker.checkNotNull( description, "description" );
+
+        myDescription = description;
+        myUndoable = undoable;
+        myDisruptive = disruptive;
+    }
+
+    //----------------------------------------------------------------------
+    // Command Implementation
+
+    public final String getDescription()
+    {
+        return myDescription;
+    }
+
+
+    public final boolean isUndoable()
+    {
+        return myUndoable;
+    }
+
+
+    public final boolean isDisruptive()
+    {
+        return myDisruptive;
+    }
+
+
+    /**
+     * Override this if undo is supported.  Throws an exception by default.
+     */
+    public void undoCommand()
+    {
+        throw new UnsupportedOperationException( "Undo not implemented" );
+    }
+
+}

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/Command.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/Command.java
                         (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/Command.java
 2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,38 @@
+package org.skycastle.util.command;
+
+/**
+ * Used for undoable commands.
+ * <p/>
+ * Encapsulates both the parameters for a command, and logic for doing and 
undoing it.
+ *
+ * @author Hans Häggström
+ */
+public interface Command
+{
+
+    /**
+     * @return an user readable description of what this command did.
+     */
+    String getDescription();
+
+    /**
+     * @return true if this is an undoable command.
+     */
+    boolean isUndoable();
+
+    /**
+     * @return true if this command should clear the previous undo and redo 
stacks.
+     */
+    boolean isDisruptive();
+
+    /**
+     * Executes the command.
+     */
+    void doCommand();
+
+    /**
+     * Undoes the command.
+     */
+    void undoCommand();
+
+}
\ No newline at end of file

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandAction.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandAction.java
                           (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandAction.java
   2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,105 @@
+package org.skycastle.util.command;
+
+import org.skycastle.util.ParameterChecker;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+
+/**
+ * An action that sends a command to an {@link CommandStack}.
+ *
+ * @author Hans Häggström
+ */
+@SuppressWarnings( { "serial", "NonSerializableFieldInSerializableClass" } )
+public abstract class CommandAction
+        extends AbstractAction
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final CommandStack myCommandStack;
+
+    //======================================================================
+    // Private Constants
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // ActionListener Implementation
+
+    public final void actionPerformed( final ActionEvent e )
+    {
+        myCommandStack.invoke( createCommand() );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    //----------------------------------------------------------------------
+    // Protected Constructors
+
+    /**
+     * Creates a new {@link CommandAction}.
+     *
+     * @param commandStack the {@link CommandStack} to use, or null if not in 
use.
+     */
+    protected CommandAction( final CommandStack commandStack,
+                             final String name )
+    {
+        this( commandStack, name, null );
+    }
+
+
+    /**
+     * Creates a new {@link CommandAction}.
+     *
+     * @param commandStack the {@link CommandStack} to use, or null if not in 
use.
+     * @param name         the name of the action.
+     * @param description  a tool tip text for the action.
+     */
+    protected CommandAction( final CommandStack commandStack,
+                             final String name,
+                             final String description )
+    {
+        this( commandStack, name, description, null );
+    }
+
+
+    /**
+     * Creates a new {@link CommandAction}.
+     *
+     * @param commandStack the {@link CommandStack} to use, or null if not in 
use.
+     * @param name         the name of the action.
+     * @param description  a tool tip text for the action.
+     * @param icon         an icon for the action.
+     */
+    protected CommandAction( final CommandStack commandStack,
+                             final String name,
+                             final String description,
+                             final Icon icon )
+    {
+        super( name, icon );
+
+        ParameterChecker.checkNotNull( name, "name" );
+        ParameterChecker.checkNotNull( commandStack, "commandStack" );
+
+        myCommandStack = commandStack;
+
+        if ( description != null )
+        {
+            putValue( SHORT_DESCRIPTION, description );
+        }
+    }
+
+    //----------------------------------------------------------------------
+    // Abstract Protected Methods
+
+    /**
+     * @return a {@link Command} for executing the action, containing both the 
parameters for the command and
+     *         the logic to run, and optionally undo logic.
+     */
+    protected abstract Command createCommand();
+
+}

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStack.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStack.java
                            (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStack.java
    2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,63 @@
+package org.skycastle.util.command;
+
+import javax.swing.*;
+
+/**
+ * A CommandStack allows executing and undoing commands.
+ * <p/>
+ * You can call invoke directly, or subclass CommandAction for UI:s.
+ *
+ * @author Hans Häggström
+ */
+public interface CommandStack
+{
+
+    /**
+     * Called when a {@link Command} is invoked from e.g. the UI.
+     *
+     * @param command the command object, which contains the necessary 
parameters and logic for running the
+     *                command.
+     */
+    void invoke( Command command );
+
+    /**
+     * @return an action that can be used to undo commands.
+     */
+    Action getUndoAction();
+
+    /**
+     * @return an action that can be used to redo commands.
+     */
+    Action getRedoAction();
+
+    /**
+     * @return true if undo can be done.
+     */
+    boolean canUndo();
+
+    /**
+     * @return true if redo can be done.
+     */
+    boolean canRedo();
+
+    /**
+     * Undoes the previous command if possible.
+     */
+    void undo();
+
+    /**
+     * Redoes the previously undone command if possible.
+     */
+    void redo();
+
+    /**
+     * @return description of the next command that can be undone.  Null if 
none available.
+     */
+    String getUndoCommandDescription();
+
+    /**
+     * @return description of the next command that can be redone.  Null if 
none available.
+     */
+    String getRedoCommandDescription();
+
+}

Added: 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
                                (rev 0)
+++ 
trunk/skycastle/modules/utils/src/main/java/org/skycastle/util/command/CommandStackImpl.java
        2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,170 @@
+package org.skycastle.util.command;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * A simple {@link CommandStack} that just invokes the tasks directly in the 
swing thread.
+ *
+ * @author Hans Häggström
+ */
+public final class CommandStackImpl
+        implements CommandStack
+{
+
+    //======================================================================
+    // Private Fields
+
+    private final Deque<Command> myUndoStack = new ArrayDeque<Command>();
+    private final Deque<Command> myRedoStack = new ArrayDeque<Command>();
+
+    @SuppressWarnings( { "serial" } )
+    private final AbstractAction myUndoAction = new AbstractAction( "Undo" )
+    {
+
+        public void actionPerformed( final ActionEvent e )
+        {
+            undo();
+        }
+
+    };
+
+    @SuppressWarnings( { "serial" } )
+    private final AbstractAction myRedoAction = new AbstractAction( "Redo" )
+    {
+
+        public void actionPerformed( final ActionEvent e )
+        {
+            redo();
+        }
+
+    };
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Constructors
+
+    /**
+     * Creates a new {@link CommandStackImpl}.
+     */
+    public CommandStackImpl()
+    {
+        updateActionStatuses();
+    }
+
+    //----------------------------------------------------------------------
+    // CommandStack Implementation
+
+    public void invoke( final Command command )
+    {
+        command.doCommand();
+
+        myRedoStack.clear();
+
+        if ( command.isDisruptive() )
+        {
+            myUndoStack.clear();
+        }
+        else if ( command.isUndoable() )
+        {
+            myUndoStack.push( command );
+        }
+
+        updateActionStatuses();
+    }
+
+
+    public Action getUndoAction()
+    {
+        return myUndoAction;
+    }
+
+
+    public Action getRedoAction()
+    {
+        return myRedoAction;
+    }
+
+
+    public boolean canUndo()
+    {
+        return !myUndoStack.isEmpty();
+    }
+
+
+    public boolean canRedo()
+    {
+        return !myRedoStack.isEmpty();
+    }
+
+
+    public void undo()
+    {
+        final Command command = myUndoStack.pop();
+
+        command.undoCommand();
+
+        myRedoStack.push( command );
+
+        updateActionStatuses();
+    }
+
+
+    public void redo()
+    {
+        final Command command = myRedoStack.pop();
+
+        command.doCommand();
+
+        myUndoStack.push( command );
+
+        updateActionStatuses();
+    }
+
+
+    public String getUndoCommandDescription()
+    {
+        final Command command = myUndoStack.peek();
+
+        if ( command != null )
+        {
+            return "Undo " + command.getDescription();
+        }
+        else
+        {
+            return "Nothing to Undo";
+        }
+    }
+
+
+    public String getRedoCommandDescription()
+    {
+        final Command command = myRedoStack.peek();
+
+        if ( command != null )
+        {
+            return "Redo " + command.getDescription();
+        }
+        else
+        {
+            return "Nothing to Redo";
+        }
+    }
+
+    //======================================================================
+    // Private Methods
+
+    private void updateActionStatuses()
+    {
+        myRedoAction.setEnabled( canRedo() );
+        myUndoAction.setEnabled( canUndo() );
+
+        myUndoAction.putValue( Action.SHORT_DESCRIPTION, 
getUndoCommandDescription() );
+        myRedoAction.putValue( Action.SHORT_DESCRIPTION, 
getRedoCommandDescription() );
+    }
+
+}

Added: 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
===================================================================
--- 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
                                (rev 0)
+++ 
trunk/skycastle/modules/utils/src/test/java/org/skycastle/util/command/CommandStackTest.java
        2008-04-26 19:14:45 UTC (rev 483)
@@ -0,0 +1,256 @@
+package org.skycastle.util.command;
+
+import junit.framework.TestCase;
+
+import javax.swing.*;
+
+/**
+ * @author Hans Häggström
+ */
+@SuppressWarnings( { "JavaDoc" } )
+public class CommandStackTest
+        extends TestCase
+{
+
+    //======================================================================
+    // Private Fields
+
+    private int[] myCounter;
+    private CommandStack myCommandStack;
+    private CommandAction myCountdownAction;
+    private CommandAction myKaboomAction;
+    private CommandAction myMessageAction;
+
+    //======================================================================
+    // Public Methods
+
+    //----------------------------------------------------------------------
+    // Test Methods
+
+    public void testUndoRedo() throws Exception
+    {
+        assertEquals( 4, myCounter[ 0 ] );
+
+        myCountdownAction.actionPerformed( null );
+        assertEquals( 3, myCounter[ 0 ] );
+
+        myCountdownAction.actionPerformed( null );
+        myCountdownAction.actionPerformed( null );
+        assertEquals( 1, myCounter[ 0 ] );
+
+        myCommandStack.undo();
+        assertEquals( 2, myCounter[ 0 ] );
+
+        myCommandStack.redo();
+        assertEquals( 1, myCounter[ 0 ] );
+    }
+
+    public void testQueryMethodsForUndo() throws Exception
+    {
+        assertFalse( myCommandStack.canUndo() );
+
+        myCountdownAction.actionPerformed( null );
+
+        assertTrue( myCommandStack.canUndo() );
+
+        myCommandStack.undo();
+
+        assertFalse( myCommandStack.canUndo() );
+
+        myCommandStack.redo();
+
+        assertTrue( myCommandStack.canUndo() );
+    }
+
+    public void testQueryMethodsForRedo() throws Exception
+    {
+        assertFalse( myCommandStack.canRedo() );
+
+        myCountdownAction.actionPerformed( null );
+
+        assertFalse( myCommandStack.canRedo() );
+
+        myCommandStack.undo();
+
+        assertTrue( myCommandStack.canRedo() );
+
+        myCountdownAction.actionPerformed( null );
+
+        assertFalse( myCommandStack.canRedo() );
+    }
+
+    public void testUndoDescription() throws Exception
+    {
+        assertEquals( "Nothing to Undo", 
myCommandStack.getUndoCommandDescription() );
+
+        myCountdownAction.actionPerformed( null );
+
+        assertEquals( "Undo Set counter to 3", 
myCommandStack.getUndoCommandDescription() );
+        assertEquals( "Undo Set counter to 3",
+                      myCommandStack.getUndoAction().getValue( 
Action.SHORT_DESCRIPTION ) );
+    }
+
+    public void testRedoDescription() throws Exception
+    {
+        assertEquals( "Nothing to Redo", 
myCommandStack.getRedoCommandDescription() );
+
+        myCountdownAction.actionPerformed( null );
+        myCountdownAction.actionPerformed( null );
+        myCommandStack.undo();
+
+        assertEquals( "Redo Set counter to 2", 
myCommandStack.getRedoCommandDescription() );
+        assertEquals( "Redo Set counter to 2",
+                      myCommandStack.getRedoAction().getValue( 
Action.SHORT_DESCRIPTION ) );
+    }
+
+    public void testUndoAction() throws Exception
+    {
+        final Action undoAction = myCommandStack.getUndoAction();
+
+        assertFalse( undoAction.isEnabled() );
+
+        myCountdownAction.actionPerformed( null );
+        assertEquals( 3, myCounter[ 0 ] );
+
+        assertTrue( undoAction.isEnabled() );
+
+        undoAction.actionPerformed( null );
+        assertEquals( 4, myCounter[ 0 ] );
+    }
+
+    public void testRedoAction() throws Exception
+    {
+        final Action redoAction = myCommandStack.getRedoAction();
+
+        assertFalse( redoAction.isEnabled() );
+
+        myCountdownAction.actionPerformed( null );
+        myCommandStack.undo();
+        assertEquals( 4, myCounter[ 0 ] );
+
+        assertTrue( redoAction.isEnabled() );
+
+        redoAction.actionPerformed( null );
+        assertEquals( 3, myCounter[ 0 ] );
+    }
+
+    public void testNonUndoableAction() throws Exception
+    {
+        myMessageAction.actionPerformed( null );
+
+        assertFalse( myCommandStack.canUndo() );
+
+        myCountdownAction.actionPerformed( null );
+        myMessageAction.actionPerformed( null );
+
+        myCommandStack.undo();
+
+        assertFalse( myCommandStack.canUndo() );
+        assertTrue( myCommandStack.canRedo() );
+    }
+
+
+    public void testDisruptiveCommand() throws Exception
+    {
+        myCountdownAction.actionPerformed( null );
+        myCountdownAction.actionPerformed( null );
+        myCountdownAction.actionPerformed( null );
+
+        myCommandStack.undo();
+
+        assertTrue( myCommandStack.canUndo() );
+        assertTrue( myCommandStack.canRedo() );
+
+        myKaboomAction.actionPerformed( null );
+
+        assertFalse( myCommandStack.canUndo() );
+        assertFalse( myCommandStack.canRedo() );
+    }
+
+    //======================================================================
+    // Protected Methods
+
+    @Override
+    protected void setUp() throws Exception
+    {
+        myCounter = new int[]{ 4 };
+
+        myCommandStack = new CommandStackImpl();
+
+        myCountdownAction = new CommandAction( myCommandStack, "Countdown" )
+        {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected Command createCommand()
+            {
+                final int oldValue = myCounter[ 0 ];
+                final int newValue = myCounter[ 0 ] - 1;
+
+                return new AbstractCommand( "Set counter to " + newValue, true 
)
+                {
+
+                    public void doCommand()
+                    {
+                        myCounter[ 0 ] = newValue;
+                    }
+
+
+                    @Override
+                    public void undoCommand()
+                    {
+                        myCounter[ 0 ] = oldValue;
+                    }
+
+                };
+            }
+
+        };
+
+
+        myKaboomAction = new CommandAction( myCommandStack, "Kaboom" )
+        {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected Command createCommand()
+            {
+                return new AbstractCommand( "Self Destructed", false, true )
+                {
+
+                    public void doCommand()
+                    {
+                        myCounter[ 0 ] = -1;
+                    }
+
+                };
+            }
+
+        };
+
+
+        myMessageAction = new CommandAction( myCommandStack, "Message" )
+        {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected Command createCommand()
+            {
+                return new AbstractCommand( "Informative Message", false )
+                {
+
+                    public void doCommand()
+                    {
+                        // println( "Self destruct sequence is ongoing, please 
evacuate" );
+                    }
+
+                };
+            }
+
+        };
+    }
+
+}


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

Other related posts:

  • » [skycastle-commits] SF.net SVN: skycastle: [483] trunk/skycastle/modules