package org.jcon.df.edit.control;

import org.jcon.param.Param;
import org.jcon.util.GenLib;
import java.awt.*;
import java.util.Hashtable;

/**
 * Creates Controls on request, thus encapsulating the
 * actual class used to implement the Control interface.
 * All static methods.
 *
 * @author Jack Harich
 */
public class ControlFactory {

//---------- Private Fields ------------------------------
// Key = type, Object = Control
// Could use ControlCreator as Object but that's extra classes
private static Hashtable controlTypes = new Hashtable();

//---------- Initialization ------------------------------
static {
// Add more as needed
addType("Boolean",   "org.jcon.df.edit.control.BooleanControl");
addType("Button",    "org.jcon.df.edit.control.JButtonControl");
addType("ButtonBar", "org.jcon.df.edit.control.ButtonBarControl");
addType("ComboBox",  "org.jcon.df.edit.control.JComboBoxControl");
addType("HTMLPane",  "org.jcon.df.edit.control.EditorPaneControl"); // A sensible alias
addType("Hyperlink", "org.jcon.df.edit.control.HyperlinkControl");
addType("Image",     "org.jcon.df.edit.control.ImageControl");
addType("InfoPane",  "org.jcon.df.edit.control.InfoPaneControl");
addType("Label",     "org.jcon.df.edit.control.LabelControl");
addType("Link",      "org.jcon.df.edit.control.LinkControl");
addType("List",      "org.jcon.df.edit.control.list.ListControl");
addType("Memo",      "org.jcon.df.edit.control.MemoControl");
addType("Spacer",    "org.jcon.df.edit.control.SpacerControl");
addType("TextArea",  "org.jcon.df.edit.control.TextAreaControl");
addType("TextField", "org.jcon.df.edit.control.JTextFieldControl");
addType("TextPane",  "org.jcon.df.edit.control.TextPaneControl");
addType("Tree",      "org.jcon.df.edit.control.tree.TreeControl");

// These are so far only used in Realm, and are discontinued - JH
addType("TextField2", "org.jcon.df.edit.control.JTextFieldControl");
addType("Button2",    "org.jcon.df.edit.control.JButtonControl");
}
//---------- Public Methods ------------------------------
/**
 * Adds the control type. The type must be unique per factory.
 * This method allows third party classes to add additional
 * types easily. The built in types are Label, TextField
 * and Link. More will follow.
 * <p>
 * The type is the "logical type" for the control. We map to
 * a className to allow easily changing the actual class
 * used for a type. This could not be done if the class name
 * was in the Param.
 */
public static void addType(String type, String className) {
    if (controlTypes.containsKey(type)) {
        throw new IllegalArgumentException("The type '" +
            type + "' has already been added.");
    } else {
        controlTypes.put(type, className);
    }
}
public static Control createControl(String name, Param param) {
    // Get controlType for type in param
    String type = param.getString("Type");
    if (type == null) {
        IllegalArgumentException ex = new IllegalArgumentException(
            "No type in param '" + param + "'.");
        GenLib.exception("ControlFactory.createControl()",
            ex.getMessage(), ex);
        throw ex;
    }    
    String className = (String)controlTypes.get(type);
    if (className == null) {
        IllegalArgumentException ex = new IllegalArgumentException(
            "Unknown type '" + type + "'.");
        GenLib.exception("ControlFactory.createControl()",
            ex.getMessage(), ex);
        throw ex;
    }
    // Create and configure control
    Control control = (Control)GenLib.createInstance(className);
    control.setName(name);
    control.setParam(param);

    control.setHelpId((String)param.getString("HelpId"));

    return control;
}
//---------- Private Methods -----------------------------
//--- Std
private static void print(String text) {
    System.out.println("ControlFactory" + text);
}

} // End class
