// StringArrayEditor.java
// $Id: StringArrayEditor.java,v 1.17 1998/02/10 13:32:41 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigadm.editors;

import java.awt.*;
import java.awt.List;
import java.awt.event.*;
import java.util.*;

import org.w3c.tools.resources.*;
import org.w3c.jigadm.*;
import org.w3c.jigsaw.admin.*;
import org.w3c.tools.widgets.*;

/**
 * An editor for StringArray attributes.  
 * @author Benoit Mahe <bmahe@sophia.inria.fr>
 */
 
public class StringArrayEditor extends AttributeEditor {


  class EditStringArrayPopup extends Frame implements ActionListener {
						      
    protected StringArrayComponent parent = null;
    protected EditorFeeder feeder         = null;
    protected String selected []             = null;
    protected List witems                    = null;
    protected Panel items                    = null;
    protected Panel pitems                   = null;
    protected ImageButton waddItem           = null;
    protected ImageButton wdelItem           = null;
    protected List wselected                 = null;
    protected Panel pselected                = null;
    protected TextEditable newItem           = null;			      
    protected boolean modified               = false;
  
   /**
    * ActionListsner implementation - One of our button was fired.
    * @param evt The ActionEvent.
    */

    public void actionPerformed(ActionEvent evt) {
      String command = evt.getActionCommand();
      if ( command.equals("add" ) ) {
	if (newItem.updated()) {
	  modified = true;
	  wselected.addItem(newItem.getText());
	}
	newItem.setDefault();
	// Add witems selection to wselected:
	int isels[] = witems.getSelectedIndexes();
	if ((isels != null) && (isels.length > 0)) {
	  // Wait until processing done to remove items...
	  modified = true;
	  for (int i = 0 ; i < isels.length ; i++) {
	    String item = witems.getItem(isels[i]);
	    wselected.addItem(item);
	    witems.deselect(isels[i]);
	  }
	  for (int i = 0 ; i < isels.length ; i++)
	    witems.delItem(isels[i]-i);
	}
      } else  if ( command.equals("del" ) ) {
	int isels[] = wselected.getSelectedIndexes();
	if ((isels != null) && (isels.length > 0)) {
	  // Wait until processing done to remove items...
	  modified = true;
	  for (int i = 0 ; i < isels.length ; i++) {
	    String item = wselected.getItem(isels[i]);
	    witems.addItem(item);
	    wselected.deselect(isels[i]);
	  }
	  for (int i = 0 ; i < isels.length ; i++) 
	    wselected.delItem(isels[i]-i);
	}
      } else  if ( command.equals("update" ) ) {
	if (modified) {
	  parent.setSelectedItems(wselected.getItems());
	  parent.setModified();
	}
	setVisible(false);
      } else  if ( command.equals("cancel" ) ) {
	modified = false;
	setVisible(false);
      } else  if ( evt.getSource().equals(newItem)) {
	if (newItem.updated()) {
	  modified = true;
	  wselected.addItem(newItem.getText());
	}
	newItem.setDefault();
	wselected.requestFocus();
      }
    }

   /**
    * Create the list of possible items, querying the feeder:
    * @param feeder The one that knows about default items.
    */
  
    protected void createDefaultItems(EditorFeeder feeder) {
      this.witems = new List(4, false);
      witems.setMultipleMode(true);
      // Feed that list:
      String items[] = feeder.getDefaultItems();
      if (items != null) {
	for (int i = 0 ; i < items.length ; i++) 
	  if ( items[i] != null )
	    witems.addItem(items[i]);
      }
    }

    protected void setDefaultItems(EditorFeeder feeder) {
      witems.removeAll();
      String items[] = feeder.getDefaultItems();
      if (items != null) {
	for (int i = 0 ; i < items.length ; i++) 
	  if ( items[i] != null )
	    witems.addItem(items[i]);
      }
    }

    protected void createSelectedItems() {
      this.wselected = new List(7, false);
      wselected.setMultipleMode(true);
    }

    protected void setSelectedItems(String selected[]) {
      // Remove any prev set items:
      wselected.removeAll();
      // Refill the list:
      if ( selected != null ) {
	for (int i = 0 ; i < selected.length ; i++) 
	  if ( selected[i] != null )
	    wselected.addItem(selected[i]);
      }
    }

    protected String[] getSelectedItems() {
      return wselected.getItems();
    }  

    protected void updateSize() {
      setSize(parent.editor.getPopupSize());
    }
						      
    public void start(String selected []) {
      modified = false;
      setSelectedItems(selected);
      setDefaultItems(feeder);
    }


    public EditStringArrayPopup(StringArrayComponent parent,
				EditorFeeder feeder,
				String selected [],
				String title)
    {
      super(title);

      PropertyManager pm = PropertyManager.getPropertyManager();
      Image left = Toolkit.getDefaultToolkit().getImage(
					    pm.getIconLocation("shadowleft"));

      Image right = Toolkit.getDefaultToolkit().getImage(
					    pm.getIconLocation("shadowright"));
      this.selected  = selected;
      this.parent   = parent;
      this.feeder   = feeder;
      this.newItem = parent.editor.getTextEditor();
      createDefaultItems(feeder);
      createSelectedItems();
      setSelectedItems(selected);
      Panel pselected = new Panel();
      pselected.add(wselected);
      
      Panel controls = new Panel();
      controls.setLayout(new BorderLayout());
      waddItem = new ImageButton(left);
      waddItem.setActionCommand("add");
      waddItem.addActionListener(this);
      Panel paddItem = new Panel();
      paddItem.add(waddItem);
      
      controls.add(paddItem, "North");
      wdelItem = new ImageButton(right);
      wdelItem.setActionCommand("del");
      wdelItem.addActionListener(this);    
      Panel pdelItem = new Panel();
      pdelItem.add(wdelItem, "Center");
      controls.add(pdelItem);
      Button Ok = new Button("Ok");
      Ok.setActionCommand("update");
      Ok.addActionListener(this);
      Button Cancel = new Button("Cancel");
      Cancel.setActionCommand("cancel");
      Cancel.addActionListener(this);
      Panel pOk = new Panel( new BorderLayout());
      pOk.add(Ok,"West");
      pOk.add(Cancel,"East");
      controls.add(pOk, "South");
      Panel items = new Panel();
      items.setLayout( new BorderLayout(0,0));
      //      newItem = new TextField(15);
      newItem.addActionListener(this);
      Panel pnewItem = new Panel();
      pnewItem.add((Component)newItem);
      items.add(pnewItem,"North");
      Panel pitems = new Panel();
      pitems.add(witems);
      items.add(pitems, "Center");
      setLayout(new BorderLayout());
      add(pselected,"West");
      add(controls, "Center");
      add(items,"East");
      updateSize();
    }
  }

  class StringArrayComponent extends ListEditor {

    protected StringArrayEditor editor     = null;
    protected EditStringArrayPopup   popup    = null;
    protected String selected []              = null;
    protected EditorFeeder feeder  = null;

    protected void edit() {
      if (popup == null)
	popup = new EditStringArrayPopup(this,
					 feeder,
					 getSelectedItems(),
					 "Edit");
      else
	popup.start(getSelectedItems());
      popup.show();
      popup.toFront();
    
    }

    public void setModified() {
      editor.setModified();
    }

    protected void setSelectedItems(String selected[]) {
      // Remove any prev set items:
      list.removeAll();
      // Refill the list:
      if ( selected != null ) {
	for (int i = 0 ; i < selected.length ; i++) 
	  if ( selected[i] != null )
	    list.addItem(selected[i]);
      }
    }

    protected String[] getSelectedItems() {
      return list.getItems();
    }

    StringArrayComponent (StringArrayEditor editor,
			  String selected[],
			  EditorFeeder feeder)
    {
      super(3,true);
      this.editor = editor;
      this.selected = selected;
      this.feeder  = feeder;
      setSelectedItems(selected);
    }

  }


  class TextEditor extends TextField implements TextEditable { 

    public boolean updated() {
      return ( (getText().length() > 0) &&
	       (! getText().equals("")) );
    }

    public void setDefault() {
      setText("");
    }

    TextEditor(int nb) {
      super(nb);
    }
    
  }

  // The StringArrayEditor itself

  /**
   * Properties - The feeder's class name.
   */
  public static final String FEEDER_CLASS_P = "feeder.class";

  protected boolean hasChanged = false;
  protected String oldvalue[]  = null;
  protected StringArrayComponent comp = null;

  protected TextEditable getTextEditor() {
    return new TextEditor(15);
  }

  protected Dimension getPopupSize() {
    return new Dimension(400,160);
  }

  protected void createComponent(EditorFeeder feeder,
				 String selected[]) {
    if ( comp == null ) 
      comp = new StringArrayComponent(this,
				      selected,
				      feeder);

  }


  protected void setModified() {
    hasChanged = true;
  }

  /**
   * Tells if the edited value has changed
   * @return true if the value changed.
   */
  public boolean hasChanged() {
    return hasChanged;
  }

  /**
   * set the current value to be the original value, ie: changed
   * must return <strong>false</strong> after a reset.
   */
  public void clearChanged() {
    hasChanged = false;
  }

  /**
   * reset the changes (if any)
   */
  public void resetChanges() {
    hasChanged = false;
    comp.setSelectedItems(oldvalue);
  }

  /**
   * Get the current value of the edited value
   * @return an object or <strong>null</strong> if the object was not
   * initialized
   */
  public Object getValue() {
    return comp.getSelectedItems();    
  }

  /**
   * Set the value of the edited value
   * @param o the new value.
   */
  public void setValue(Object o) {
    this.oldvalue = (String[]) o;
    comp.setSelectedItems(oldvalue);
  }

  /**
   * get the Component created by the editor.
   * @return a Component
   */
  public Component getComponent() {
    return comp;
  }

  /**
   * Initialize the editor
   * @param w the ResourceWrapper father of the attribute
   * @param a the Attribute we are editing
   * @param o the value of the above attribute
   * @param p some Properties, used to fine-tune the editor
   */
  public void initialize(RemoteResourceWrapper w
			 , Attribute a
			 , Object o
			 , Properties p) 
    throws RemoteAccessException
  {
    // Get the feeder class fromproperties:
    EditorFeeder feeder      = null;
    String       feederClass = null;
    
    feederClass = (String)p.get(FEEDER_CLASS_P);
    if ( feederClass == null )
      throw new RuntimeException("StringArrayEditor mis-configuration: "+
				 FEEDER_CLASS_P + " property undefined.");
    try {
      Class c = Class.forName(feederClass);
      feeder  = (EditorFeeder) c.newInstance();
      feeder.initialize(w,p);
    } catch (Exception ex) {
      ex.printStackTrace();
      throw new RuntimeException("StringArrayEditor mis-configured: "+
				 " unable to instantiate "+
				 feederClass +".");
    }
    createComponent(feeder, (String[]) o);
    oldvalue = (String[]) o;
  }

  public StringArrayEditor() {
    super();
  }

}

