// HashtableAttributeEditor.java
// $Id: HashtableAttributeEditor.java,v 1.11 1998/02/10 13:32:31 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.jigsaw.admin.*;
import org.w3c.jigadm.*;
import org.w3c.tools.widgets.*;
import org.w3c.util.*;

/**
 * HashtableAttributeEditor :
 * @author Benoit Mahe <bmahe@sophia.inria.fr>
 */

public class HashtableAttributeEditor extends AttributeEditor {

  class HashtableAttributePopup extends Frame implements ActionListener,
							 ItemListener
  {

    protected HashtableAttributeComponent parent = null;
    protected ArrayDictionary table                    = null;
    protected List keys                          = null;
    protected TextField tkey                     = null;
    protected TextField tvalue                   = null;
    protected boolean modified                   = false;
    protected String selectedKey                 = null;


    public void itemStateChanged(ItemEvent e) {
      if (e.getStateChange() == ItemEvent.SELECTED) {
	Integer idx = (Integer)e.getItem();
	String key = keys.getItem(idx.intValue());
	if (key != null) {
	  String value = (String)table.get(key);
	  tkey.setText(key);
	  selectedKey = key;
	  tvalue.setText(value);
	  tkey.requestFocus();
	}
      }
    }


    public void actionPerformed(ActionEvent evt) {
      String command = evt.getActionCommand();
      if ( command.equals("add" ) ) {
	String key = tkey.getText();
	String value = tvalue.getText();
	if (key.length() > 0) {
	  table.put(key,value);
	  updateKeys();
	  modified = true;
	}
      } else  if ( command.equals("replace" ) ) {
	if (selectedKey != null)
	  table.remove(selectedKey);
	String key = tkey.getText();
	String value = tvalue.getText();
	if (key.length() > 0) {
	  table.put(key,value);
	  updateKeys();
	  modified = true;
	}
      } else  if( command.equals("del" ) ) {
	int isels[] = keys.getSelectedIndexes();
	if ((isels != null) && (isels.length > 0)) {
	  modified = true;
	  for (int i = 0 ; i < isels.length ; i++) {
	    String key = keys.getItem(isels[i]);
	    table.remove(key);
	    keys.deselect(isels[i]);
	  }
	  for (int i = 0 ; i < isels.length ; i++)
	    keys.delItem(isels[i]-i);
	}
	tkey.setText("");
	tvalue.setText("");
      } else  if( command.equals("update" ) ) {
	if (modified) {
	  parent.setTable(table);
	  parent.setModified();
	  modified = false;
	}
	tkey.setText("");
	tvalue.setText("");      
	setVisible(false);
      } else  if( command.equals("cancel" ) ) {
	modified = false;
	tkey.setText("");
	tvalue.setText("");      
	setVisible(false);
      } else  if( evt.getSource() == tkey ) {
	tvalue.requestFocus();
      } else  if( evt.getSource() == tvalue ) {
	String key = tkey.getText();
	String value = tvalue.getText();
	if (key.length() > 0) {
	  table.put(key,value);
	  updateKeys();
	  modified = true;
	}
	tkey.requestFocus();
      }
    }

    protected void updateKeys() {
      tkey.setText("");
      tvalue.setText("");
      keys.removeAll();
      Enumeration e = table.keys();
      while (e.hasMoreElements())
	keys.addItem((String)e.nextElement());
    }
  

    protected void updateSize() {
      setSize(350,230);
    }

    public void start(ArrayDictionary table) {
      this.table  = table;
      updateKeys();
      selectedKey = null;
      modified = false;
    }

    HashtableAttributePopup(HashtableAttributeComponent parent,
			    ArrayDictionary table,
			    String title) 
    {
      super(title);
      this.parent = parent;
      this.table  = table;
    
      GridBagLayout layout = new GridBagLayout();
      GridBagConstraints c = new GridBagConstraints();
      c.fill = GridBagConstraints.NONE;
      c.insets = new Insets(5,5,5,5);
      setLayout(layout);

      Label lkey = new Label("Key");
      Label lvalue = new Label("Value");

      tkey = new TextField(15);
      tkey.addActionListener(this);
      tvalue = new TextField(15);
      tvalue.addActionListener(this);

      keys = new List(5,true);
      keys.addItemListener(this);

      Button addB = new Button("add");
      addB.setActionCommand("add");
      addB.addActionListener(this);

      Button removeB = new Button("Remove");
      removeB.setActionCommand("del");
      removeB.addActionListener(this);

      Button replaceB = new Button("Replace");
      replaceB.setActionCommand("replace");
      replaceB.addActionListener(this);

      Button okB = new Button("Ok");
      okB.setActionCommand("update");
      okB.addActionListener(this);

      Button cancelB = new Button("Cancel");
      cancelB.setActionCommand("cancel");
      cancelB.addActionListener(this);

      c.fill = GridBagConstraints.NONE;
      c.gridwidth = GridBagConstraints.RELATIVE;
      c.anchor = GridBagConstraints.CENTER;
      layout.setConstraints(lkey,c);
      add(lkey);

      c.gridwidth = GridBagConstraints.REMAINDER;
      c.anchor = GridBagConstraints.CENTER;
      layout.setConstraints(lvalue,c);
      add(lvalue);

      c.fill = GridBagConstraints.BOTH;
      c.gridwidth = GridBagConstraints.RELATIVE;
      layout.setConstraints(tkey,c);
      add(tkey);

      c.gridwidth = GridBagConstraints.REMAINDER;
      layout.setConstraints(tvalue,c);
      add(tvalue);

      c.gridwidth = GridBagConstraints.RELATIVE;
      //    c.gridheight = 2;
      layout.setConstraints(keys,c);
      add(keys);

      c.fill = GridBagConstraints.NONE;


      Panel control = new Panel( new BorderLayout());
      control.add(addB, "North");
      control.add(replaceB, "Center");
      control.add(removeB,"South");
      c.gridwidth = GridBagConstraints.REMAINDER;
      layout.setConstraints(control,c);
      add(control);

      c.fill = GridBagConstraints.BOTH;

      c.gridwidth = GridBagConstraints.RELATIVE;
      layout.setConstraints(okB,c);
      add(okB);

      c.gridwidth = GridBagConstraints.REMAINDER;
      layout.setConstraints(cancelB,c);
      add(cancelB);

      updateSize();
      updateKeys();
    }

  }

  class HashtableAttributeComponent extends ListEditor {

    protected HashtableAttributeEditor editor = null;
    protected HashtableAttributePopup  popup  = null;
    protected ArrayDictionary hashtable             = null;
  
    protected void edit() {
      if (popup == null)   
	popup = new HashtableAttributePopup(this,
					    (ArrayDictionary)hashtable.clone(),
					    "Edit");
      else 
	popup.start((ArrayDictionary)hashtable.clone());
      popup.show();
      popup.toFront();
    }

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

    protected void setTable(ArrayDictionary table) {
      if (table == null) {
	hashtable = new ArrayDictionary(5);
	return;
      }
      hashtable = table;
      Enumeration keys = table.keys();
      list.removeAll();
      while (keys.hasMoreElements())
	list.addItem((String)keys.nextElement());
    }

    protected ArrayDictionary getTable() {
      return hashtable;
    } 
  
    HashtableAttributeComponent(HashtableAttributeEditor editor,
				ArrayDictionary table) 
    {
      super(3,false);
      this.editor = editor;
      setTable(table);
    } 
			      

  }

  // The HashtableAttributeEditor itself

  protected boolean hasChanged               = false;
  protected HashtableAttributeComponent comp = null;
  protected ArrayDictionary oldValue               = null;

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

  protected void createComponent(ArrayDictionary table) {
    if (comp == null)
      comp = new HashtableAttributeComponent(this,table);
  }

  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.setTable(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.getTable();
  }

  /**
   * Set the value of the edited value
   * @param o the new value.
   */
  public void setValue(Object o) {
    this.oldValue = (ArrayDictionary)o;
    comp.setTable(oldValue);
  }

  /**
   * 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
  {
    createComponent((ArrayDictionary)o);
    oldValue = (ArrayDictionary)o;
  }

  public HashtableAttributeEditor() {
    super();
  }

  public static void main(String argv[]) {
    ArrayDictionary table = new ArrayDictionary(20);
    table.put("title","salut les copains");
    table.put("title2","salut les copains 2");    
    table.put("title3","salut les copains 3");
    table.put("title4","salut les copains 4");
    table.put("title5","salut les copains 5");

    Frame f = new Frame ("ArrayDictionary Editor");
    HashtableAttributeEditor editor = new HashtableAttributeEditor();
    try {
      editor.initialize( null, null, table, null);
    } catch (Exception e) {}
    f.add("Center",editor.getComponent());
    f.pack();
    f.show();
  }

}
