/*
 * JavaForm.java    1.0 97/08/28
 *
 * Copyright (c) 1997 Netscape Communications Corporation
 *
 * Netscape grants you a non-exclusive, royalty free, license to use,
 * modify and redistribute this software in source and binary code form,
 * provided that i) this copyright notice and license appear on all copies of
 * the software; and ii) Licensee does not utilize the software in a manner
 * which is disparaging to Netscape.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * See the CDK License Agreement for additional terms and conditions.
 * created: 2/97 cls
 */


package netscape.peas;



import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeEvent;
import java.applet.*;
import java.awt.*;

/**
 * Example Java Applet which shows a "one row" form, if wired to another component
 * which implements the "Row" interface.
 */
public class JavaForm extends Applet implements Row {

    //-----------------------------------------------------------------------------------------------------------
    // constructor

    /**
     * Default constuctor.
     */
    public JavaForm() {
    }

    /**
     * Initialize this applet.  Set size to something completely arbitrary.
     */
    public void init() {
        super.init();
        resize(283,190);
    }

    /**
     * Heleper method to determine the column number of one of our TextFields
     */
    private int findComponentColumnNumber( TextField oTextField ) {
        for ( int i=0; i < getNumColumns(); i++ ) {
            if ( oTextField == maColumnValueViews[i] ) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Handle (AWT 1.02) events.  We take appropriate action which may result in
     * Bean style (AWT 1.1) events being fired.
     */
    public boolean handleEvent( Event oEvent ) {
        switch ( oEvent.id ) {
            case Event.LOST_FOCUS: {
                if (oEvent.target instanceof TextField ) {
                    TextField oTextField = (TextField)oEvent.target;
                    int iColumn = findComponentColumnNumber( oTextField );
                    if ( moRowSupport.isValidColumnNumber( iColumn ) ) {
                        String sNewValue;
                        synchronized (this ) {
                            sNewValue = oTextField.getText();
                        }
                        if ( null == sNewValue ) {
                            sNewValue = "";
                        }
                        setValueByNumber( iColumn, sNewValue, null );
                        return true;
                    }
                }
                break;
            }
            case Event.GOT_FOCUS:
                break;
        }
        return false;
    }



    //-----------------------------------------------------------------------------------
    // GetInterface interface

    /**
     * Return an object which implements this specified (fully qualified) interface name.
     * If this interface is not implemented, return null.
     */
    public Object getInterface( String sInterfaceName ) {
        return moRowSupport.getInterface( sInterfaceName );
    }



    //-----------------------------------------------------------------------------------
    // Row interface

    public void setColumnNames( String[] aColumnNames, int[] aColumnWidths, NotifyList oNotify ) {
        moRowSupport.setColumnNames( aColumnNames, aColumnWidths, oNotify );
    }

    // end of Row interface
    //-----------------------------------------------------------------------------------



    //-----------------------------------------------------------------------------------------------------------
    // RowProvider interface

	/**
	 * Return the number of columns.
	 */
	public int getNumColumns() {
	    return moRowSupport.getNumColumns();
    }

    /**
     * Return an array of column names
     */
    public String[] getColumnNames() {
	    return moRowSupport.getColumnNames();
    }

    /**
     * Return an array of column names
     */
    public int[] getColumnWidths() {
	    return moRowSupport.getColumnWidths();
    }

    /**
     * Given a column's index (0..NumColumns), return its name
     */
    public String getColumnName( int iColumnNumber ) {
	    return moRowSupport.getColumnName( iColumnNumber );
    }

   /**
     * return values held by this row support object
     * clone here of in client??
     */
    public Object[] getColumnValues() {
        return moRowSupport.getColumnValues();
    }

    /**
     * Given a column name, get its value.  This is a
     * "Dynamic-getter" method.  Unlike "normal" setter
     * methods ("void getFoo();"), dynamic-getters can be used
     * for properties whose names are known at compile time.
     */
    public Object getValueByName( String sColumnName ) {
	    return moRowSupport.getValueByName( sColumnName );
    }

    /**
     * Another flavor of "Dynamic-getter" method.
     * See @getValueByName.
     */
	public Object getValueByNumber( int iColumnNumber ) {
	    return moRowSupport.getValueByNumber( iColumnNumber );
    }

    /**
     * Classes, such as JavaForm which implement the RowProvider (part of Row) interface
     * must suppport firing the PropertyChangeEvent and the RowChangeEvent.  JavaForm
     * delegates these to moRowSupport, which in turn delegates them to RowChangeSupport.
     */
    public void addPropertyChangeListener( PropertyChangeListener x ) {
	    moRowSupport.addPropertyChangeListener( x );
    }

    /**
     * Classes, such as JavaForm which implement the RowProvider (part of Row) interface
     * must suppport firing the PropertyChangeEvent and the RowChangeEvent.  JavaForm
     * delegates these to moRowSupport, which in turn delegates them to RowChangeSupport.
     */
    public void removePropertyChangeListener( PropertyChangeListener x ) {
       moRowSupport.removePropertyChangeListener( x );
    }

    /**
     * Classes, such as JavaForm which implement the RowProvider (part of Row) interface
     * must suppport firing the PropertyChangeEvent and the RowChangeEvent.  JavaForm
     * delegates these to moRowSupport, which in turn delegates them to RowChangeSupport.
     */
    public void addRowChangeListener( RowChangeListener oRowReceiver ){
       moRowSupport.addRowChangeListener( oRowReceiver );
    }

    /**
     * Classes, such as JavaForm which implement the RowProvider (part of Row) interface
     * must suppport firing the PropertyChangeEvent and the RowChangeEvent.  JavaForm
     * delegates these to moRowSupport, which in turn delegates them to RowChangeSupport.
     */
    public void removeRowChangeListener( RowChangeListener oRowReceiver ) {
       moRowSupport.removeRowChangeListener( oRowReceiver );
    }

    public void fireRowChange( int iChangeType, String sColumnAffected, Object oOldValue, Object oNewValue, RowProvider oRowProvider, NotifyList oNotify ) {
        moRowSupport.fireRowChange( iChangeType, sColumnAffected, oOldValue, oNewValue, oRowProvider, oNotify );
    }

    // end of RowProvider interface
    //-----------------------------------------------------------------------------------------------------------


    //-----------------------------------------------------------------------------------------------------------
    // RowReceiver interface

    /**
     * Handle property change events for which we are listening.  RowSupport
     * calls back up to SetValueByNumber where we can update our view.
     */
	public void propertyChange( PropertyChangeEvent oEvent ) {
        moRowSupport.propertyChange( oEvent );
    } // propertyChange


    /**
     * Twister rowChange event. For us it means: "column info has changed".
     */
     public void rowChange( RowChangeEvent oEvent ) {
        moRowSupport.rowChange( oEvent );
     } // rowChange


    /**
     * Given a column's name, set its value to be this new value.
     * This is a "dymanic-setter". See @RowReceiver.getValueByName
     */
    public void setValueByName( String sColumnName, Object oNewValue) {
        setValueByName( sColumnName, oNewValue, null );
    }
    public void setValueByName( String sColumnName, Object oNewValue, NotifyList oNotify ) {
        moRowSupport.setValueByName( sColumnName, oNewValue, oNotify );
    } // setValueByName

    /**
     * Different flavor "dynamic-setter".  See @setValueByName.
     */
    public void setValueByNumber( int iColumnNumber, Object oNewValue, NotifyList oNotify ) {
        moRowSupport.setValueByNumber( iColumnNumber, oNewValue, oNotify );

        // update the "view"
        if ( moRowSupport.isValidColumnNumber( iColumnNumber ) ) {
            synchronized ( this ) {
                maColumnValueViews[iColumnNumber].setText( oNewValue.toString() );
            }
            maColumnValueViews[iColumnNumber].invalidate();
        }
    }

    /**
     * This method can be called by the data provider to inform us (the client) of its column names
     * This is typically when this object registers itself as a listener by calling
     * by calling addPropertyChangeListener
     *
     * alternatively, a RowProvider interface could be passed to the client and it the client
     * could then "pull" the column names (and any other data) from this provider
     */
    public boolean initializeColumnInfo( RowProvider oRowProvider ) {


        // let Rowprovider handle the model part...
        if ( moRowSupport.initializeColumnInfo( oRowProvider ) ) {

            int iNumColumns = getNumColumns();
            String aColumnNames[] = getColumnNames();

            //------------------------ take care of "view" part -----------//
            removeAll();  // components from this container
            GridLayout oGrid = new GridLayout( iNumColumns, 2, 5, 5 );
            setLayout( oGrid );

            // setup labels
            maColumnLabelViews = new Label[iNumColumns];
            maColumnValueViews = new TextField[iNumColumns];

            for ( int j = 0; j < iNumColumns; j++ ) {

                maColumnLabelViews[j] = new Label( aColumnNames[j], Label.RIGHT );
                add( maColumnLabelViews[j] );
                maColumnLabelViews[j].invalidate();

                maColumnValueViews[j] = new TextField("");
                add( maColumnValueViews[j] );
                maColumnValueViews[j].reshape( 0, 0, 120, 15 );
                maColumnValueViews[j].invalidate();
            }
            layout();
            show();
            return true;
        }
        return false;

    } // initializeColumnInfo


    // end of RowReceiver interface
    //-----------------------------------------------------------------------------------------------------------

    public void firePropertyChange(String propertyName,	Object oldValue, Object newValue) {
        moRowSupport.firePropertyChange( propertyName, oldValue, newValue );
    }


    //-----------------------------------------------------------------------------------------------------------
    // member variables

    Label maColumnLabelViews[] = null;       // read-only
    TextField maColumnValueViews[] = null;

    private RowSupport moRowSupport = new RowSupport( this, false );

}
