/* CompoundEdit.java -- Combines multiple UndoableEdits.
   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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 2, or (at your option)
any later version.

GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package javax.swing.undo;

import java.util.Vector;

/**
 * An editing action that consists of multiple
 * <code>UndoableEdits</code>.
 *
 * <p>The use of a <code>CompoundEdit</code> is divided in two separate
 * phases.</p>
 *
 * <ol>
 * <li>In the first phase, the <code>CompoundEdit</code> is
 *     initialized.  After a new instance of <code>CompoundEdit</code> has
 *     been created, {@link #addEdit(UndoableEdit)} is called for each
 *     element of the compound.  To terminate the initialization phase,
 *     call {@link #end()}.</li>
 * <li>In the second phase, the the <code>CompoundEdit</code> can be
 *     used, typically by invoking {@link #undo()} and
 *     {@link #redo()}.</li>
 * </ol>
 *
 * @author Andrew Selkirk (aselkirk@sympatico.ca)
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class CompoundEdit
  extends AbstractUndoableEdit
{
  /**
   * The identifier of this class in object serialization. Determined
   * using the serialver tool of Sun J2SE 1.4.1_01.
   */
  private static final long serialVersionUID = -6512679249930119683L;


  /**
   * The <code>UndoableEdit</code>s being combined into a compound
   * editing action.
   */
  protected Vector<UndoableEdit> edits;


  /**
   * Indicates whether the creation of this CompoundEdit is still in
   * progress. Initially, the value of this flag is
   * <code>true</code>. The {@link #end()} method changes the flag to
   * <code>false</code>.
   */
  private boolean inProgress;


  /**
   * Constructs a new CompoundEdit.
   */
  public CompoundEdit()
  {
    edits = new Vector<UndoableEdit>();
    inProgress = true;
  }


  /**
   * Undoes all edits that are part of of this
   * <code>CompoundEdit</code>. The compound elements will receive the
   * <code>undo</code> message in the reverse order of addition.
   *
   * @throws CannotUndoException if {@link #canUndo()} returns
   * <code>false</code>. This can happen if {@link #end()} has not
   * been called on this <code>CompoundEdit</code>, or if this edit
   * has already been undone.
   *
   * @see #canUndo()
   * @see #redo()
   */
  public void undo()
    throws CannotUndoException
  {
    // AbstractUndoableEdit.undo() will throw a CannotUndoException if
    // canUndo returns false.
    super.undo();

    for (int i = edits.size() - 1; i >= 0; i--)
      edits.elementAt(i).undo();
  }


  /**
   * Redoes all edits that are part of of this
   * <code>CompoundEdit</code>. The compound elements will receive the
   * <code>undo</code> message in the same order as they were added.
   *
   * @throws CannotRedoException if {@link #canRedo()} returns
   * <code>false</code>. This can happen if {@link #end()} has not
   * been called on this <code>CompoundEdit</code>, or if this edit
   * has already been redone.
   *
   * @see #canRedo()
   * @see #undo()
   */
  public void redo()
    throws CannotRedoException
  {
    // AbstractUndoableEdit.redo() will throw a CannotRedoException if
    // canRedo returns false.
    super.redo();

    for (int i = 0; i < edits.size(); i++)
      edits.elementAt(i).redo();
  }


  /**
   * Returns the the <code>UndoableEdit</code> that was last added to
   * this compound.
   */
  protected UndoableEdit lastEdit()
  {
    if (edits.size() == 0)
      return null;
    else
      return edits.elementAt(edits.size() - 1);
  }


  /**
   * Informs this edit action, and all compound edits, that they will
   * no longer be used. Some actions might use this information to
   * release resources such as open files.  Called by {@link
   * UndoManager} before this action is removed from the edit queue.
   *
   * <p>The compound elements will receive the
   * <code>die</code> message in the reverse order of addition.
   */
  public void die()
  {
    for (int i = edits.size() - 1; i >= 0; i--)
      edits.elementAt(i).die();

    super.die();
  }


  /**
   * Incorporates another editing action into this one, thus forming a
   * combined edit.
   *
   * <p>If this edit&#x2019;s {@link #end()} method has been called
   * before, <code>false</code> is returned immediately. Otherwise,
   * the {@linkplain #lastEdit() last added edit} is given the
   * opportunity to {@linkplain UndoableEdit#addEdit(UndoableEdit)
   * incorporate} <code>edit</code>.  If this fails, <code>edit</code>
   * is given the opportunity to {@linkplain
   * UndoableEdit#replaceEdit(UndoableEdit) replace} the last added
   * edit.  If this fails as well, <code>edit</code> gets added as a
   * new compound to {@link #edits}.
   *
   * @param edit the editing action being added.
   *
   * @return <code>true</code> if <code>edit</code> could somehow be
   * incorporated; <code>false</code> if <code>edit</code> has not
   * been incorporated because {@link #end()} was called before.
   */
  public boolean addEdit(UndoableEdit edit)
  {
    UndoableEdit last;

    // If end has been called before, do nothing.
    if (!inProgress)
      return false;

    last = lastEdit();

    // If edit is the very first edit, just add it to the list.
    if (last == null)
    {
      edits.add(edit);
      return true;
    }

    // Try to incorporate edit into last.
    if (last.addEdit(edit))
      return true;

    // Try to replace last by edit.
    if (edit.replaceEdit(last))
    {
      edits.set(edits.size() - 1, edit);
      return true;
    }

    // If everything else has failed, add edit to the list of compound
    // edits.
    edits.add(edit);
    return true;
  }


  /**
   * Informs this <code>CompoundEdit</code> that its construction
   * phase has been completed. After this method has been called,
   * {@link #undo()} and {@link #redo()} may be called, {@link
   * #isInProgress()} will return <code>false</code>, and all attempts
   * to {@linkplain #addEdit(UndoableEdit) add further edits} will
   * fail.
   */
  public void end()
  {
    inProgress = false;
  }


  /**
   * Determines whether it would be possible to undo this editing
   * action. The result will be <code>true</code> if {@link #end()}
   * has been called on this <code>CompoundEdit</code>, {@link #die()}
   * has not yet been called, and the edit has not been undone
   * already.
   *
   * @return <code>true</code> to indicate that this action can be
   * undone; <code>false</code> otherwise.
   *
   * @see #undo()
   * @see #canRedo()
   */
  public boolean canUndo()
  {
    return !inProgress && super.canUndo();
  }


  /**
   * Determines whether it would be possible to redo this editing
   * action. The result will be <code>true</code> if {@link #end()}
   * has been called on this <code>CompoundEdit</code>, {@link #die()}
   * has not yet been called, and the edit has not been redone
   * already.
   *
   * @return <code>true</code> to indicate that this action can be
   * redone; <code>false</code> otherwise.
   *
   * @see #redo()
   * @see #canUndo()
   */
  public boolean canRedo()
  {
    return !inProgress && super.canRedo();
  }


  /**
   * Determines whether the initial construction phase of this
   * <code>CompoundEdit</code> is still in progress.  During this
   * phase, edits {@linkplain #addEdit(UndoableEdit) may be
   * added}. After initialization has been terminated by calling
   * {@link #end()}, {@link #undo()} and {@link #redo()} can be used.
   *
   * @return <code>true</code> if the initialization phase is still in
   * progress; <code>false</code> if {@link #end()} has been called.
   *
   * @see #end()
   */
  public boolean isInProgress()
  {
    return inProgress;
  }


  /**
   * Determines whether this editing action is significant enough for
   * being seperately undoable by the user. A typical significant
   * action would be the resizing of an object. However, changing the
   * selection in a text document would usually not be considered
   * significant.
   *
   * <p>A <code>CompoundEdit</code> is significant if any of its
   * elements are significant.
   */
  public boolean isSignificant()
  {
    for (int i = edits.size() - 1; i >= 0; i--)
      if (edits.elementAt(i).isSignificant())
        return true;

    return false;
  }


  /**
   * Returns a human-readable, localized name that describes this
   * editing action and can be displayed to the user.
   *
   * <p>The implementation delegates the call to the {@linkplain
   * #lastEdit() last added edit action}. If no edit has been added
   * yet, the inherited implementation will be invoked, which always
   * returns an empty string.
   */
  public String getPresentationName()
  {
    UndoableEdit last;

    last = lastEdit();
    if (last == null)
      return super.getPresentationName();
    else
      return last.getPresentationName();
  }


  /**
   * Calculates a localized message text for presenting the undo
   * action to the user.
   *
   * <p>The implementation delegates the call to the {@linkplain
   * #lastEdit() last added edit action}. If no edit has been added
   * yet, the {@linkplain
   * AbstractUndoableEdit#getUndoPresentationName() inherited
   * implementation} will be invoked.
   */
  public String getUndoPresentationName()
  {
    UndoableEdit last;

    last = lastEdit();
    if (last == null)
      return super.getUndoPresentationName();
    else
      return last.getUndoPresentationName();
  }


  /**
   * Calculates a localized message text for presenting the redo
   * action to the user.
   *
   * <p>The implementation delegates the call to the {@linkplain
   * #lastEdit() last added edit action}. If no edit has been added
   * yet, the {@linkplain
   * AbstractUndoableEdit#getRedoPresentationName() inherited
   * implementation} will be invoked.
   */
  public String getRedoPresentationName()
  {
    UndoableEdit last;

    last = lastEdit();
    if (last == null)
      return super.getRedoPresentationName();
    else
      return last.getRedoPresentationName();
  }


  /**
   * Calculates a string that may be useful for debugging.
   */
  public String toString()
  {
    return super.toString()
      + " inProgress: " + inProgress
      + " edits: " + edits;
  }
}
