// (c) MIT 2003.  All rights reserved.

// $Id: UndoableWidgetRegistry.java,v 1.7 2003/03/06 00:40:39 moltmans Exp $
// Time-stamp: <2000-03-11 18:59:36 moltmans>
package rec.sys;


///////////////////////////////////////////////////////////////////////////////
//
// FILE:	WidgetRegistry.java
//
// AUTHOR:	Manoj D. Muzumdar
//		archon@ai.mit.edu
//
// DATE:	June, 1998
//
// COPYRIGHT:	Massachusetts Institute of Technology
//		All rights reserved.
//
// PURPOSE:	Drawing recognition
//
// HISTORY:     September, 1998
//              MDM
//              modified to account for new transition structure
//
///////////////////////////////////////////////////////////////////////////////


import java.util.*;
import rec.util.*;

/**
 * All necessary changes are made to the Registry before any
 *     notifications are made.
 */
public class UndoableWidgetRegistry extends WidgetRegistry
{
  TransitionRecorder recorder;
  Surface surface;

  public UndoableWidgetRegistry( Surface surface,
				 TransitionRecorder recorder )
  {
    this.surface = surface;
    this.recorder = recorder;
  }

  /////////////////////////////////////////////////////////////////////////////


  public void add( Widget w )
  {
    Transition t =  createAddTransition( w );
    super.add( w );

    recorder.record( t );
  }
  

  public void remove( Widget w )
  {
    Console.writeln( "*** REMOVE " + w + " ***" );
    Transition t =  createAddTransition( w );
    super.remove( w );

    recorder.record( t.getRedoTransition() );
    Console.writeln( "*** END REMOVE " + w + " ***" );
  }
  
  private Transition createAddTransition( Widget widget )
  {
    final Widget w = widget;

    TableEntry tmpte = lookup( w );
    final TableEntry te = (tmpte != null) ? (TableEntry)(tmpte.clone()) : null;

    return new FlipTransition( surface ) {
      public void doUndo( )
	{
	  doRemove( w );
	}
      public void doRedo( )
	{
	  doAdd( w );

	  // restore all the registeration of the widget
	  if ( te != null )
	    {
	      HashSet se = te.m_Registry;
	      Iterator it = se.iterator();
	      while( it.hasNext() )
		doRegister( (Registerable)it.next(), w );

	      // restore all the things widget was registered to
	      if ( te.listener() )
		{
		  it = te.m_Registered.iterator();
		  while( it.hasNext() )
		    doRegister( (Registerable)w, (Widget)it.next() );
		}
	    }
	}
      public String name()
	{
	  return "reg-add[" + w.getId() + "]";
	}
    };
  }


  public void replace( Widget ow, Widget nw )
  {
    super.replace( ow, nw );

    recorder.record( createReplaceTransition( ow, nw ) );
  }

  private Transition createReplaceTransition( Widget old_widget,
					      Widget new_widget )
  {
    final Widget ow = old_widget;
    final Widget nw = new_widget;

    return new FlipTransition( surface ) {
      public void doUndo( )
	{
	  replace( nw, ow, false );
	}
      public void doRedo( )
	{
	  replace( ow, nw, false );
	}
      public String name()
	{
	  return "reg-replace[" + ow.getId() + "->" + nw.getId() + "]";
	}
    };
  }


  public void replace( HashSet ows, Widget nw )
  {
    super.replace( ows, nw );

    recorder.record( createReplaceTransition( ows, nw ) );
  }
  
  
  public void replace( Widget ow, HashSet nws )
  {
    super.replace( ow, nws );

    recorder.record( createReplaceTransition( nws,
					      ow ).getRedoTransition() );
  }

  private Transition createReplaceTransition( HashSet old_widget_set,
					      Widget new_widget )
  {
    final HashSet ows = old_widget_set;
    final Widget nw = new_widget;

    return new FlipTransition( surface ) {
      public void doUndo( )
	{
	  replace( nw, ows, false );
	}
      public void doRedo( )
	{
	  replace( ows, nw, false );
	}
      public String name()
	{
	  return "reg-replace(m-2-1)";
	}
    };
  }


  /**
   * Registerable registers for which Id to get notifications
   *     about.
   */
  public void register( Registerable r, Widget w )
  {
    super.register( r, w );

    recorder.record( createRegisterTransition( r, w ) );
  }
  
  private Transition createRegisterTransition( Registerable reg,
					       Widget wid )
  {
    final Registerable r = reg;
    final Widget w = wid;

    return new FlipTransition( surface ) {
      public void doUndo( )
	{
	  unregister( r, w );
	}
      public void doRedo( )
	{
	  register( r, w );
	}
      public String name()
	{
	  return "reg-register";
	}
    };
  }


  public void alter( Widget w, AlterTransition t )
  {
    super.alter( w, t, recorder.isRecording() );

    recorder.record( t );
  }
  
}



