// ClientResource.java
// $Id: ClientResource.java,v 1.2 1997/07/30 14:10:05 ylafon Exp $  
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.tools.resources.tests;

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

import w3c.tools.resources.rmi.*;

class StringPropertySetter implements ActionListener {
    ClientResource target = null;
    String property = null;

    // TextListener (cheap editor for String only)
    public void actionPerformed(ActionEvent evt) {
	try {
	    TextField field = (TextField) evt.getSource();
System.out.println(target.name+"."+property+"="+field.getText());
	    target.getTarget().setValue(property, field.getText());
	} catch (Exception ex) {
	    // notify the client resource of error
	    ex.printStackTrace();
	}
    }

    StringPropertySetter(ClientResource target, String property) {
	this.target = target;
	this.property = property;
    }
}

// A really simple (RS) resource editor

class ResourceEditor extends Panel {
    ClientResource target = null;
    

    private void init() {
	GridBagLayout layout = new GridBagLayout();
	setLayout(layout);
	// Grid bag magic:
	GridBagConstraints ct = null;
	GridBagConstraints cv = null;
	// Create the title constraints:
	ct         = new GridBagConstraints() ;
	ct.gridx   = GridBagConstraints.RELATIVE ;
	ct.anchor  = GridBagConstraints.EAST ;
	ct.weighty = 1.0 ;
	// Create the value constraints:
	cv           = new GridBagConstraints() ;
	cv.gridx     = GridBagConstraints.RELATIVE ;
	cv.gridwidth = GridBagConstraints.REMAINDER ;
	cv.fill      = GridBagConstraints.HORIZONTAL ;
	cv.anchor    = GridBagConstraints.WEST ;
	cv.weightx   = 1.0 ;
	cv.weighty   = 1.0 ;
	// For each property, create appropriate fields:
	try {
	    RemotePropertyDescriptor p[] = target.getProperties();
	    for (int i = 0 ; i < p.length ; i++) {
		Label label = new Label(p[i].getName(), Label.LEFT);
		layout.setConstraints(label, ct);
		add(label);
		// This is over simplified:
		Object value = target.getTarget().getValue(p[i].getName());
		TextField text = new TextField();
		text.setText((value == null) ? "" : value.toString());
		if ( p[i].getPropertyType().equals(String.class) ) {
			StringPropertySetter s = null;
			s = new StringPropertySetter(target, p[i].getName());
			text.addActionListener(s);
		} 
		layout.setConstraints(text, cv);
		add(text);
	    }
	} catch (Exception ex) {
	    // FIXME notify the ClientResource of error
	    ex.printStackTrace();
	}
    }

    ResourceEditor(ClientResource target) {
	super();
	this.target = target;
	init();
    }

}

/**
 * The "client" view of a remote resource
 * A cache, in fact, of client side loaded resources. Thic class would also
 * be responsible for being an event listener on the wrapped resource, so that
 * changes could appear asynchronously, etc, etc, etc
 * NOTE: We DO NOT cache the structure, for good reasons
 */

public class ClientResource {
    public static String UNFOLDED_ICON 
    = "/u/koala/0/koala/leon/dev/java/classes/koala/images/diropened.gif";
    public static String FOLDED_ICON
    = "/u/koala/0/koala/leon/dev/java/classes/koala/images/dir.gif";
    public static String DEFAULT_ICON 
    = "/u/koala/0/koala/leon/dev/java/classes/koala/images/file.gif";
    
    protected static Hashtable resources = new Hashtable();

    RemoteResource target = null;
    // We do cache certain fields (most commonly used ones)
    public String name = null;
    public String icon = null;
    // Properties of that target:
    public RemotePropertyDescriptor properties[] = null;
    // Do we have an editor on that object ?
    protected ResourceEditor editor = null;

    /**
     * Get a client resource for given resource
     */

    public static synchronized ClientResource get(RemoteResource r)
	throws RemoteException
    {
	ClientResource cr = (ClientResource) resources.get(r);
	if ( cr == null ) {
	    cr = new ClientResource(r);
	    resources.put(r, cr);
	}
	return cr;
    }

    RemoteResource getTarget() {
	return target;
    }

    protected void init() 
	throws RemoteException
    {
	try {
	    // Initialize the name
	    this.name = (String) target.getValue("name");
	    // Get the property list:
	    this.properties = target.getProperties();
	    // Init the icon (if possible)
	    for (int i = 0 ; i < properties.length ; i++) {
		if ( properties[i].getName().equals("icon") ) {
		    this.icon = (String) target.getValue("icon");
		    break;
		}
	    }
	} catch (IllegalAccessException ex) {
	    throw new InternalError("illegal access to resource !");
	}
    }

    public RemotePropertyDescriptor[] getProperties() {
	return properties;
    }


    /**
     * Get the (main) icon to display in place of the resource
     * @return An image (that's broken, oeuf corse)
     */

    public java.awt.Image getIcon(boolean folded) {
	String imageName = null;
	// Do we really have an icon ?
	if ( icon != null ) {
	    imageName = icon;
	} else if ( isContainer() ) {
	    imageName = folded ? FOLDED_ICON : UNFOLDED_ICON;
	} else {
	    imageName = DEFAULT_ICON;
	}
	return Toolkit.getDefaultToolkit().getImage(imageName);
    }

    public boolean isContainer() {
	return target instanceof RemoteResourceContainer;
    }

    /**
     * Get (or build) an editor, viewing that object
     * @return A panel.
     */

    public synchronized Panel getEditor() {
	if ( editor == null )
	    editor = new ResourceEditor(this);
	return editor;
    }

    private ClientResource(RemoteResource resource) 
	throws RemoteException
    {
	this.target = resource;
	init();
    }

}
