/* UndoableEditSupport.java --
   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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.Iterator;
import java.util.Vector;

import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;

/**
 * A helper class for supporting {@link
 * javax.swing.event.UndoableEditListener}.
 *
 * @author Andrew Selkirk (aselkirk@sympatico.ca)
 * @author Sascha Brawer (brawer@dandelis.ch)
 */
public class UndoableEditSupport
{
  /**
   * The number of times that {@link #beginUpdate()} has been called
   * without a matching call to {@link #endUpdate()}.
   */
  protected int updateLevel;


  /**
   * compoundEdit
   */
  protected CompoundEdit compoundEdit;


  /**
   * The currently registered listeners.
   */
  protected Vector listeners = new Vector();


  /**
   * The source of the broadcast UndoableEditEvents.
   */
  protected Object realSource;


  /**
   * Constructs a new helper for broadcasting UndoableEditEvents.  The
   * events will indicate the newly constructed
   * <code>UndoableEditSupport</code> instance as their source.
   *
   * @see #UndoableEditSupport(java.lang.Object)
   */
  public UndoableEditSupport()
  {
    realSource = this;
  }


  /**
   * Constructs a new helper for broadcasting UndoableEditEvents.
   *
   * @param realSource the source of the UndoableEditEvents that will
   * be broadcast by this helper. If <code>realSource</code> is
   * <code>null</code>, the events will indicate the newly constructed
   * <code>UndoableEditSupport</code> instance as their source.
   */
  public UndoableEditSupport(Object realSource)
  {
    if (realSource == null)
      realSource = this;
    this.realSource = realSource;
  }


  /**
   * Returns a string representation of this object that may be useful
   * for debugging.
   */
  public String toString()
  {
    // Note that often, this.realSource == this. Therefore, dumping
    // realSource without additional checks may lead to infinite
    // recursion. See Classpath bug #7119.
    return super.toString() + " updateLevel: " + updateLevel
      + " listeners: " + listeners + " compoundEdit: " + compoundEdit;
  }


  /**
   * Registers a listener.
   *
   * @param val the listener to be added.
   */
  public synchronized void addUndoableEditListener(UndoableEditListener val)
  {
    listeners.add(val);
  }


  /**
   * Unregisters a listener.
   * @param val the listener to be removed.
   */
  public synchronized void removeUndoableEditListener(UndoableEditListener val)
  {
    listeners.removeElement(val);
  }


  /**
   * Returns an array containing the currently registered listeners.
   */
  public synchronized UndoableEditListener[] getUndoableEditListeners()
  {
    UndoableEditListener[] result = new UndoableEditListener[listeners.size()];
    return (UndoableEditListener[]) listeners.toArray(result);
  }


  /**
   * Notifies all registered listeners that an {@link
   * UndoableEditEvent} has occured.
   *
   * <p><b>Lack of Thread Safety:</b> It is <em>not</em> safe to call
   * this method from concurrent threads, unless the call is protected
   * by a synchronization on this <code>UndoableEditSupport</code>
   * instance.
   *
   * @param edit the edit action to be posted.
   */
  protected void _postEdit(UndoableEdit edit)
  {
    UndoableEditEvent event;
    Iterator iter;

    // Do nothing if we have no listeners.
    if (listeners.isEmpty())
      return;

    event = new UndoableEditEvent(realSource, edit);

    // We clone the vector because this allows listeners to register
    // or unregister listeners in their undoableEditHappened method.
    // Otherwise, this would throw exceptions (in the case of
    // Iterator, a java.util.ConcurrentModificationException; in the
    // case of a direct loop over the Vector elements, some
    // index-out-of-bounds exception).
    iter = ((Vector) listeners.clone()).iterator();
    while (iter.hasNext())
      ((UndoableEditListener) iter.next()).undoableEditHappened(event);
  }


  /**
   * If {@link #beginEdit} has been called (so that the current
   * update level is greater than zero), adds the specified edit
   * to {@link #compoundEdit}. Otherwise, notify listeners of the
   * edit by calling {@link #_postEdit(UndoableEdit)}.
   *
   * <p><b>Thread Safety:</b> It is safe to call this method from any
   * thread without external synchronization.
   *
   * @param edit the edit action to be posted.
   */
  public synchronized void postEdit(UndoableEdit edit)
  {
    if (compoundEdit != null)
      compoundEdit.addEdit(edit);
    else
      _postEdit(edit);
  }


  /**
   * Returns the current update level.
   */
  public int getUpdateLevel()
  {
    return updateLevel;
  }


  /**
   * Starts a (possibly nested) update session. If the current update
   * level is zero, {@link #compoundEdit} is set to the result of the
   * {@link #createCompoundEdit} method. In any case, the update level
   * is increased by one.
   *
   * <p><b>Thread Safety:</b> It is safe to call this method from any
   * thread without external synchronization.
   */
  public synchronized void beginUpdate()
  {
    if (compoundEdit == null)
      compoundEdit = createCompoundEdit();
    ++updateLevel;
  }


  /**
   * Creates a new instance of {@link #CompoundEdit}. Called by {@link
   * #beginUpdate}. If a subclass wants {@link #beginUpdate} to work
   * on a specific {@link #compoundEdit}, it should override this
   * method.
   *
   * @returns a newly created instance of {@link #CompoundEdit}.
   */
  protected CompoundEdit createCompoundEdit()
  {
    return new CompoundEdit();
  }


  /**
   * Ends an update session. If the terminated session was the
   * outermost session, {@link #compoundEdit} will receive an
   * <code>end</code> message, and {@link #_postEdit} gets called in
   * order to notify any listeners. Finally, the
   * <code>compoundEdit</code> is discarded.
   *
   * <p><b>Thread Safety:</b> It is safe to call this method from any
   * thread without external synchronization.
   */
  public synchronized void endUpdate()
  {
    if (updateLevel == 0)
      throw new IllegalStateException();

    if (--updateLevel > 0)
      return;

    compoundEdit.end();
    _postEdit(compoundEdit);
    compoundEdit = null;
  }
}
