/*
 *This library is free software; you can redistribute it and/or
 *modify it under the terms of the GNU Lesser General Public
 *License as published by the Free Software Foundation; either
 *version 2.1 of the License, or (at your option) any later version.
 *
 *This library 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
 *Lesser General Public License for more details.
 *
 *You should have received a copy of the GNU Lesser General Public
 *License along with this library; if not, write to the Free Software
 *Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/* 
 * This software is copyright by Phillip Lord (p.lord@hgmp.mrc.ac.uk)
 */

package uk.ac.man.bioinf.gui.optionable; // Package name inserted by JPack
import java.awt.Dimension;
import java.awt.Point;
import java.util.HashMap;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import uk.ac.man.bioinf.apps.optionable.NullOptionHandler;
import uk.ac.man.bioinf.apps.optionable.OptionHandler;
import uk.ac.man.bioinf.apps.optionable.Optionable;
import uk.ac.man.bioinf.debug.Debug;
import uk.ac.man.bioinf.apps.optionable.OptionableStateException;

/**
 * OptionableJFrame.java
 *
 *
 * Created: Fri May 07 16:45:36 1999
 *
 * @author Phillip Lord
 * @version $Id: OptionableJFrame.java,v 1.2 2001/04/11 17:04:42 lord Exp $
 */

public abstract class OptionableJFrame extends JFrame
  implements Optionable
{
  private String optionableName;
  
  private OptionHandler optionHandler;
  private boolean sizeSetAsOption = false;
  private boolean locationSetAsOption = false;
  private boolean haveOptioned = false;
  
  public OptionableJFrame( String optionableName )
  {
    this( optionableName, "" );
  }

  /**
   * An internal frame with a title
   * @param title
   */
  public OptionableJFrame( String optionableName, String title )
  {
    this( optionableName, title, false );
  }

  /**
   * No title. However if the param is true this class will not register
   * its optionable status until explicitly told, rather than in the constructor.
   * Subclasses which have their own options should use this option if they need
   * to complete their own setOptions before their constructor is complete. 
   * @param delayOptionable delay setting options until explicitly told
   * @see #forceOptionable
   */
  public OptionableJFrame( String optionableName, boolean delayOptionable )
  {
    this( optionableName, "", delayOptionable );
  }
  
  public OptionableJFrame( String optionableName, String title, 
                           boolean delayOptionable )
  {
    this( optionableName, title, delayOptionable, null );
  }
  
  /**
   * A title and the ability to delay the registering of the optionable
   * status
   * @param optionableName the name used to identify this Frame to the
   * optionable library. 
   * @param title the title
   * @param delayOptionable delay setting optionable status
   */
  public OptionableJFrame( String optionableName, String title,
                           boolean delayOptionable, OptionHandler handler )
  {
    super( title );
    this.optionableName = optionableName;
    this.optionHandler = optionHandler;
    
    if( !delayOptionable ){
      forceOptionable();
    }
  }
 
  
  public void setOptions() throws OptionableStateException
  {
    if( haveOptioned ){
      throw new OptionableStateException( "Have already set the optionable status of this frame" );
    }
    forceOptionable();
  }
    
  /**
   * Force the setting the optionable status now. This method
   * excepts if it is called more than once per object, or if a constructor without
   * the delayOptionable parameter has NOT been used
   * @throws RuntimeException if called illegally
   */
  protected void forceOptionable()
  {
    if( haveOptioned ) 
      throw new RuntimeException( "Have already set the optionable status of this frame" );
    getOptionHandler().addOptionable( this );
    haveOptioned = true;
  }
  
  /**
   * This sets the size of the frame, only if it hasnt been set as an option. This
   * allows a default size to be set outside the constructor. The setSize() method 
   * sets the size regardless of whether it has been set previously
   * @param x the width
   * @param y the height
   */
  public void setDefaultSize( int x, int y )
  {
    //Set the size only if it hasnt been set by an option. 
    if( !sizeSetAsOption ){
      super.setSize( x, y );
    }
  }
  
  /**
   * Pretty much the same as setDefaultSize
   * @see #setDefaultSize
   * @param x the x location
   * @param y the y location
   */
  public void setDefaultLocation( int x, int y )
  {
    if( !locationSetAsOption ){
      super.setLocation( x, y );
    }
  }
  
  /**
   * Pack the frame if the size hasnt been sized by its options
   */
  public void defaultPack()
  {
    if( !locationSetAsOption ){
      super.pack();
    }
  }
  
  /**
   * An implementation of the Optionable interface. Subclasses overriding this method
   * should call super.getOptions. Also the constructor documentation and the delayOptionable
   * parameter should be considered.
   * @return the options
   */
  public Object getOptions()
  {
    HashMap options = new HashMap();
    //Place the options regarding size and location into a hashmap.
    options.put( "frameSize", getSize() );
    options.put( "frameLocation", getLocation() );
    return options;
  }
  
  /**
   * Implementation of the Optionable Interface. 
   * @see getOptions
   * @param param1
   */
  public void setOptions(Object param1) 
  {
    try{
      if ( param1 == null ) return;
      HashMap options = (HashMap)param1;
      //Size and location
      setSize( new Dimension( 300, 300 ) );
      setSize( (Dimension)options.get( "frameSize" ) );
      sizeSetAsOption = true;
      setLocation( (Point)options.get( "frameLocation" ) );
      locationSetAsOption = true;      
    }
    catch( NullPointerException ex ){
      //We can just ignore this. It should only occur when the options have
      //not be set for the first time
      if( Debug.debug ){
	System.out.println( "Null pointer exception occuring in OptionableInternalFrame, setOptions" );
	ex.printStackTrace();
      }
    }
    catch( ClassCastException ex ){
      //This should only occur during development
      if( Debug.debug ){
	System.out.println( "ClassCastException occuring in OptionableInternalFrame, setOptions" );
      }
    }
  }

  /**
   * Implementation of the OptionableInterface
   * @param OptionHandler the optionhandler
   */
  public void setOptionHandler( OptionHandler optionHandler ) 
  {
    this.optionHandler = optionHandler;
  }

  /**
   * Implementation of the Optionable interface
   * @return the option handler
   */
  public OptionHandler getOptionHandler() 
  {
    if( optionHandler == null ){
      return getDefaultOptionHandler();
    }
    else{
      return optionHandler;
    }
  }
  
  /**
   * Subclasses must provide this, either on a class or instance basis
   * @return the Option group name
   */
  public String getOptionGroupName()
  {
    return optionableName;
  }
  
  private static OptionHandler defaultOptionHandler;
  public static void setDefaultOptionHandler( OptionHandler optionHandler )
  {
    defaultOptionHandler = optionHandler;
  }
  
  public static OptionHandler getDefaultOptionHandler()
  {
    if( defaultOptionHandler == null ){
      return NullOptionHandler.getInstance();
    }
    return defaultOptionHandler;
  }
} // OptionableJFrame



/*
 * ChangeLog
 * $Log: OptionableJFrame.java,v $
 * Revision 1.2  2001/04/11 17:04:42  lord
 * Added License agreements to all code
 *
 * Revision 1.1  2001/02/19 17:42:53  lord
 * Initial checkin
 *
 * Revision 1.3  1999/10/14 14:00:52  phillip2
 * Changed packages and a few other bits and bobs
 *
 * Revision 1.3  1999-10-12 14:47:46+01  phillip2
 * Outdated (renamed to 'D:\Home\rcs\D\Home\java\sources\photofit\editor\gui\OptionableJFrame.java,v').
 *
 * Revision 1.3  1999-10-04 16:24:19+01  phillip2
 * Outdated (renamed to 'D:\Home\rcs\D\Home\java\sources\photofit\editor\gui\OptionableJFrame.java,v').
 *
 * Revision 1.2  1999-10-01 16:56:20+01  phillip2
 * Added import statements due to changed package structure
 *
 * Revision 1.1  1999-05-14 14:39:05+01  phillip2
 * Initial revision
 *
 */
