Index: /trunk/gli/src/org/greenstone/gatherer/cdm/FormatManager.java
===================================================================
--- /trunk/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 5231)
+++ /trunk/gli/src/org/greenstone/gatherer/cdm/FormatManager.java	(revision 5232)
@@ -46,4 +46,5 @@
 import org.greenstone.gatherer.cdm.Format;
 import org.greenstone.gatherer.msm.ElementWrapper;
+import org.greenstone.gatherer.util.GSDLSiteConfig;
 import org.greenstone.gatherer.util.Utility;
 import org.w3c.dom.*;
@@ -55,4 +56,10 @@
     extends DOMProxyListModel {
 
+    static final private String BLANK = "blank";
+    static final private String FLAG  = "flag";
+    static final private String VALUE = "value";
+
+    /** This flag is set if some change has occured to the format commands. When a collection has been built for previewing, and the greenstone local library server is used, then we have to send commands to remove then add the new collection. */
+    private boolean formats_changed = false;
     /** The controls used to edit the format commands. */
     private Control controls = null;
@@ -81,4 +88,5 @@
 	    add(root, format, target_node);
 	    Gatherer.c_man.configurationChanged();
+	    formats_changed = true;
 	}
     }
@@ -101,4 +109,15 @@
 	return result;
     }
+
+    public Format getFormat(String name) {
+	int model_size = getSize();
+	for(int index = 0; index < model_size; index++) {
+	    Format format = (Format) getElementAt(index);
+	    if(format.getName().equals(name)) {
+		return format;
+	    }
+	}
+	return null;
+    }
     
     /** Method to retrieve this managers controls.
@@ -118,4 +137,55 @@
 	remove(format);
 	Gatherer.c_man.configurationChanged();
+	formats_changed = true;
+    }
+
+    private HashMap buildDefaultMappings(ArrayList features_model, ArrayList parts_model) {
+	System.err.println("buildDefaultMappings(): replace me with something that reads in a data xml file.");
+	return new HashMap();
+    }
+
+    private ArrayList buildFeatureModel() {
+	// Rebuild feature model.
+	ArrayList feature_model = new ArrayList();
+	// Add the set options
+	for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) {
+	    feature_model.add(new Entry(Format.DEFAULT_FEATURES[i]));
+	}
+	// Now the classifiers.
+	for(int j = 0; j < CollectionDesignManager.classifier_manager.getSize(); j++) {
+	    feature_model.add(new Entry(CollectionDesignManager.classifier_manager.getClassifier(j)));
+	}
+	Collections.sort(feature_model);
+	return feature_model;
+    }
+
+    private ArrayList buildPartModel() {
+	System.err.println("buildPartModel(): replace me with something that reads in a data xml file.");
+	ArrayList part_model = new ArrayList();
+	part_model.add("");
+	part_model.add("DateList");
+	part_model.add("HList");
+	part_model.add("Invisible");
+	part_model.add("VList");
+	return part_model;
+    }
+
+    private ArrayList buildVariableModel() {
+	System.err.println("buildVariableModel(): replace me with something that reads in a data xml file.");
+	ArrayList variable_model = new ArrayList();
+	variable_model.add("[Text]");
+	variable_model.add("[link]");
+	variable_model.add("[/link]");
+	variable_model.add("[icon]");
+	variable_model.add("[num]");
+	variable_model.add("[parent():_]");
+	variable_model.add("[parent(Top):_]");
+	variable_model.add("[parent(All'_'):_]");
+	Vector elements = Gatherer.c_man.getCollection().msm.getAssignedElements();
+	for(int i = 0; i < elements.size(); i++) {
+	    variable_model.add("[" + ((ElementWrapper)elements.get(i)).getName() + "]");
+	}
+	Collections.sort(variable_model);
+	return variable_model;
     }
 
@@ -146,236 +216,171 @@
 	extends JPanel 
 	implements Control {
-	/** Do we ignore selection changing events (mainly because we're generating them!) */
-	private boolean ignore = false;
-	private boolean new_entry = true;
-	private boolean ready = false;
-	private ButtonGroup button_group = null;
-	private CardLayout card_layout = null;
-	private Dimension LABEL_SIZE = new Dimension(175,25);
-	private Format current_format = null;
-	private String view_type = "custom";
-	private JButton add = null;
-	private JButton insert = null;
-	private JButton preview = null;
-	private JButton remove = null;
-	private JComboBox feature = null;
-	private JComboBox part = null;
-	private JComboBox special = null;
-	private JLabel editor_label = null;
-	private JLabel feature_label = null;
-	private JLabel format_list_label = null;
-	private JLabel part_label = null;
-	private JLabel special_label = null;
-	private JLabel title = null;
-	private JLabel value_label = null;
-	private JList format_list = null;
-	private JPanel blank_pane = null;
-	private JPanel control_pane = null;
-	private JPanel editor_pane = null;
-	private JPanel feature_pane = null;
-	private JPanel format_list_pane = null;
-	private JPanel header_pane = null;
-	private JPanel inner_button_pane = null;
-	private JPanel inner_state_pane = null;
-	private JPanel inner_value_pane = null;
-	private JPanel options_pane = null;
-	private JPanel outer_button_pane = null;
-	private JPanel part_pane = null;
-	private JPanel special_pane = null;
-	private JPanel state_pane = null;
-	private JPanel value_pane = null;
-	private JPanel view_pane = null;
-	private JTextArea editor = null;
-	private JTextArea instructions = null;
-	private JTextField value = null;
-	private JToggleButton off = null;
-	private JToggleButton on = null;
-	private String BLANK = "blank";
-	private String CUSTOM = "custom";
-	private String FLAG = "flag";
-	private String PARAM = "param";
-	private Vector part_model = null;
-	private Vector special_model = null;
+	
+	private ArrayList feature_model;
+	private ArrayList part_model;
+	private ArrayList variable_model;
+	private boolean ignore_event = false;
+	private boolean ready = false; // Are these controls available to be refreshed
+	private CardLayout card_layout;
+	private HashMap default_mappings;
+	private JButton add_button;
+	private JButton insert_button;
+	private JButton remove_button;
+	private JButton replace_button;
+	private JButton reset_button;
+	private JCheckBox enabled_checkbox;
+	private JComboBox feature_combobox;
+	private JComboBox part_combobox;
+	private JComboBox variable_combobox;
+	private JList format_list;
+	private JTextArea instructions_textarea;
+	private JTextArea editor_textarea;
+	private JPanel control_pane;
+	private JPanel part_pane;
+	private JPanel selection_pane;
+	private String view_type;
+
 	public FormatControl() {
-	    ArrayList feature_model = buildFeatureModel();
-	    part_model = new Vector();
-	    part_model.add("");
-	    part_model.add("DateList");
-	    part_model.add("HList");
-	    part_model.add("Invisible");
-	    part_model.add("VList");
-	    special_model = new Vector();
-	    special_model.add("[Text]");
-	    special_model.add("[link]");
-	    special_model.add("[/link]");
-	    special_model.add("[icon]");
-	    special_model.add("[num]");
-	    special_model.add("[parent():_]");
-	    special_model.add("[parent(Top):_]");
-	    special_model.add("[parent(All'_'):_]");
-	    Vector elements = Gatherer.c_man.getCollection().msm.getAssignedElements();
-	    for(int i = 0; i < elements.size(); i++) {
-		special_model.add("[" + ((ElementWrapper)elements.get(i)).getName() + "]");
-	    }
-	    Collections.sort(special_model);
+	    feature_model = buildFeatureModel();
+	    part_model = buildPartModel();
+	    variable_model = buildVariableModel();
+	    default_mappings = buildDefaultMappings(feature_model, part_model);
+
 	    // Create
-	    add = new JButton(get("Add"));
-	    add.setEnabled(false);
-	    blank_pane = new JPanel();
-	    button_group = new ButtonGroup();
+	    JPanel instructions_pane = new JPanel();
+	    JLabel title_label = new JLabel(get("Title"));
+	    title_label.setHorizontalAlignment(JLabel.CENTER);
+	    title_label.setOpaque(true);
+	    instructions_textarea = new JTextArea(get("Instructions"));
+	    instructions_textarea.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
+	    instructions_textarea.setEditable(false);
+	    instructions_textarea.setLineWrap(true);
+	    instructions_textarea.setRows(6);
+	    instructions_textarea.setWrapStyleWord(true);
+
+	    JLabel format_label = new JLabel(get("Assigned_Formats"));
+	    format_list = new JList(model);
+
+	    selection_pane = new JPanel();
+	    JPanel feature_pane = new JPanel();
+	    JLabel feature_label = new JLabel(get("Feature"));
+	    feature_label.setPreferredSize(Utility.LABEL_SIZE);
+	    feature_combobox = new JComboBox(feature_model.toArray());
+	    feature_combobox.setEditable(false);
+	    part_pane = new JPanel();
+	    JLabel part_label = new JLabel(get("Part"));
+	    part_label.setPreferredSize(Utility.LABEL_SIZE);
+	    part_combobox = new JComboBox(part_model.toArray());
+	    part_combobox.setEditable(false);
+
+	    JPanel center_pane = new JPanel();
+
 	    card_layout = new CardLayout();
 	    control_pane = new JPanel();
-	    editor = new JTextArea();
-	    editor.setBackground(Gatherer.config.getColor("coloring.editable_background", false));
-	    editor.setCaretPosition(0);
-	    editor.setLineWrap(true);
-	    editor.setWrapStyleWord(false);
-	    editor_label = new JLabel(get("Editor"));
-	    editor_label.setHorizontalAlignment(JLabel.CENTER);
-	    editor_pane = new JPanel();
-	    feature = new JComboBox(feature_model.toArray());
-	    feature.setEditable(false);
-	    feature_label = new JLabel(get("Feature"));
-	    feature_label.setPreferredSize(LABEL_SIZE);
-	    format_list = new JList(model);
-	    format_list_label = new JLabel(get("Assigned_Formats"));
-	    format_list_pane = new JPanel();
-	    feature_pane = new JPanel();
-	    header_pane = new JPanel();
-	    inner_button_pane = new JPanel();
-	    inner_state_pane = new JPanel();
-	    inner_value_pane = new JPanel();
-	    insert = new JButton(get("Insert"));
-	    instructions = new JTextArea(get("Instructions"));
-	    instructions.setBackground(Gatherer.config.getColor("coloring.collection_tree_background", false));
-	    instructions.setEditable(false);
-	    instructions.setLineWrap(true);
-	    instructions.setRows(6);
-	    instructions.setWrapStyleWord(true);
-	    off = new JToggleButton(get("Off"));
-	    off.setSelected(false);
-	    on = new JToggleButton(get("On"));
-	    on.setSelected(true);
-	    options_pane = new JPanel();
-	    outer_button_pane = new JPanel();
-	    part = new JComboBox(part_model);
-	    part.setEditable(false);
-	    part_label = new JLabel(get("Part"));
-	    part_label.setPreferredSize(LABEL_SIZE);
-	    part_pane = new JPanel();
-	    preview = new JButton(get("Preview"));
-	    preview.setEnabled(false);
-	    remove = new JButton(get("Remove"));
-	    remove.setEnabled(false);
-	    special = new JComboBox(special_model);
-	    special_label = new JLabel(get("Special"));
-	    special_label.setHorizontalAlignment(JLabel.CENTER);
-	    special_pane = new JPanel();
-	    state_pane = new JPanel();
-	    title = new JLabel(get("Title"));
-	    title.setHorizontalAlignment(JLabel.CENTER);
-	    title.setOpaque(true);
-	    value = new JTextField();
-	    value_label = new JLabel(get("Value"));
-	    value_pane = new JPanel();
-	    view_pane = new JPanel();
+
+	    JPanel blank_pane = new JPanel();
+
+	    JPanel editor_pane = new JPanel();
+	    JPanel editor_header_pane = new JPanel();
+	    JLabel editor_label = new JLabel(get("Editor"));
+	    reset_button = new JButton(get("Reset"));
+	    reset_button.setMnemonic(KeyEvent.VK_T);
+	    editor_textarea = new JTextArea();
+	    editor_textarea.setBackground(Gatherer.config.getColor("coloring.editable_background", false));
+	    editor_textarea.setCaretPosition(0);
+	    editor_textarea.setLineWrap(true);
+	    editor_textarea.setRows(6);
+	    editor_textarea.setWrapStyleWord(false);
+
+	    JPanel variable_pane = new JPanel();
+	    JLabel variable_label = new JLabel(get("Variable"));
+	    variable_combobox = new JComboBox(variable_model.toArray());
+	    insert_button = new JButton(get("Insert"));
+	    insert_button.setMnemonic(KeyEvent.VK_I);
+
+	    JPanel flag_pane = new JPanel();
+	    enabled_checkbox = new JCheckBox(get("Enabled"));
+
+	    JPanel button_pane = new JPanel();
+	    add_button = new JButton(get("Add"));
+	    add_button.setEnabled(false);
+	    add_button.setMnemonic(KeyEvent.VK_A);
+	    replace_button = new JButton(get("Replace"));
+	    replace_button.setEnabled(false);
+	    replace_button.setMnemonic(KeyEvent.VK_C);
+	    remove_button = new JButton(get("Remove"));
+	    remove_button.setEnabled(false);
+	    remove_button.setMnemonic(KeyEvent.VK_R);
+
 	    // Connect
-	    add.addActionListener(new AddListener());
-	    button_group.add(on);
-	    button_group.add(off);
-	    editor.getDocument().addDocumentListener(new EditorListener());
-	    feature.addActionListener(new FeatureListener());
+	    add_button.addActionListener(new AddListener());
+	    insert_button.addActionListener(new InsertListener());
+	    remove_button.addActionListener(new RemoveListener());
+	    replace_button.addActionListener(new ReplaceListener());
+	    reset_button.addActionListener(new ResetListener());
+	    enabled_checkbox.addActionListener(new EnabledListener());
+	    feature_combobox.addActionListener(new FeatureListener());
+	    part_combobox.addActionListener(new PartListener());
+	    editor_textarea.getDocument().addDocumentListener(new EditorListener());
 	    format_list.addListSelectionListener(new FormatListListener());
-	    insert.addActionListener(new InsertListener());
-	    off.addActionListener(new StateListener());
-	    on.addActionListener(new StateListener());
-	    part.addActionListener(new PartListener());
-	    preview.addActionListener(new PreviewListener());
-	    remove.addActionListener(new RemoveListener());
-	    value.addKeyListener(new ValueListener());
-				// Layout
-	    instructions.setBorder(BorderFactory.createEmptyBorder(2,5,2,5));
-
-	    header_pane.setLayout(new BorderLayout());
-	    header_pane.add(title, BorderLayout.NORTH);
-	    header_pane.add(new JScrollPane(instructions), BorderLayout.CENTER);
-
-	    format_list_label.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
-
-	    format_list_pane.setLayout(new BorderLayout());
-	    format_list_pane.add(format_list_label, BorderLayout.NORTH);
-	    format_list_pane.add(new JScrollPane(format_list), BorderLayout.CENTER);
-
-	    feature_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
-
-	    feature_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+
+	    // Layout
+	    instructions_pane.setLayout(new BorderLayout());
+	    instructions_pane.add(title_label, BorderLayout.NORTH);
+	    instructions_pane.add(new JScrollPane(instructions_textarea), BorderLayout.CENTER);
+	    instructions_pane.add(format_label, BorderLayout.SOUTH);
+
 	    feature_pane.setLayout(new BorderLayout());
 	    feature_pane.add(feature_label, BorderLayout.WEST);
-	    feature_pane.add(feature, BorderLayout.CENTER);
-
-	    part_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
-
-	    part_pane.setBorder(BorderFactory.createEmptyBorder(5,0,5,0));
+	    feature_pane.add(feature_combobox, BorderLayout.CENTER);
+
 	    part_pane.setLayout(new BorderLayout());
 	    part_pane.add(part_label, BorderLayout.WEST);
-	    part_pane.add(part, BorderLayout.CENTER);
-
-	    options_pane.setLayout(new GridLayout(2,1));
-	    options_pane.add(feature_pane);
-	    options_pane.add(part_pane);
-
-	    inner_state_pane = new JPanel(new GridLayout(1,2));
-	    inner_state_pane.add(on);
-	    inner_state_pane.add(off);
-
-	    state_pane.setLayout(new BorderLayout());
-	    state_pane.add(inner_state_pane, BorderLayout.NORTH);
-	    state_pane.add(new JPanel(), BorderLayout.CENTER);
-
-	    value_label.setBorder(BorderFactory.createEmptyBorder(0,0,0,5));
-
-	    inner_value_pane.setLayout(new BorderLayout());
-	    inner_value_pane.add(value_label, BorderLayout.WEST);
-	    inner_value_pane.add(value, BorderLayout.CENTER);
-
-	    value_pane.setLayout(new BorderLayout());
-	    value_pane.add(inner_value_pane, BorderLayout.NORTH);
-	    value_pane.add(new JPanel(), BorderLayout.CENTER);
-
-	    special_pane.setLayout(new GridLayout(3,1));
-	    special_pane.add(special_label);
-	    special_pane.add(special);
-	    special_pane.add(insert);
+	    part_pane.add(part_combobox, BorderLayout.CENTER);
+
+	    selection_pane.setLayout(new GridLayout(2,1,0,2));
+	    selection_pane.add(feature_pane);
+	    selection_pane.add(part_pane);
+
+	    flag_pane.add(enabled_checkbox);
+
+	    editor_header_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	    editor_header_pane.setLayout(new GridLayout(1,3));
+	    editor_header_pane.add(editor_label);
+	    editor_header_pane.add(new JPanel());
+	    editor_header_pane.add(reset_button);
+
+	    variable_pane.setBorder(BorderFactory.createEmptyBorder(2,0,2,0));
+	    variable_pane.setLayout(new GridLayout(1,3));
+	    variable_pane.add(variable_label);
+	    variable_pane.add(variable_combobox);
+	    variable_pane.add(insert_button);
 
 	    editor_pane.setLayout(new BorderLayout());
-	    editor_pane.add(editor_label, BorderLayout.NORTH);
-	    editor_pane.add(new JScrollPane(editor), BorderLayout.CENTER);
-	    editor_pane.add(special_pane, BorderLayout.EAST);
-
-				// Magic for view_pane card layout.
-	    view_pane.setLayout(card_layout);
-	    view_pane.add(editor_pane, CUSTOM);
-	    view_pane.add(state_pane, FLAG);
-				//view_pane.add(value_pane, PARAM);
-
-	    inner_button_pane.setLayout(new GridLayout(1,2));
-	    inner_button_pane.add(add);
-	    inner_button_pane.add(remove);
-
-	    outer_button_pane.setBorder(BorderFactory.createEmptyBorder(5,0,0,0));
-	    outer_button_pane.setLayout(new GridLayout(1,1));
-	    outer_button_pane.add(inner_button_pane);
-				//outer_button_pane.add(preview);
-
-	    control_pane.setLayout(new BorderLayout());
-	    control_pane.add(options_pane, BorderLayout.NORTH);
-	    control_pane.add(view_pane, BorderLayout.CENTER);
-	    control_pane.add(outer_button_pane, BorderLayout.SOUTH);
+	    editor_pane.add(editor_header_pane, BorderLayout.NORTH);
+	    editor_pane.add(new JScrollPane(editor_textarea), BorderLayout.CENTER);
+	    editor_pane.add(variable_pane, BorderLayout.SOUTH);
+
+	    control_pane.setLayout(card_layout);
+	    control_pane.add(flag_pane, FLAG);
+	    control_pane.add(editor_pane, VALUE);
+	    control_pane.add(blank_pane, BLANK);
+
+	    button_pane.setLayout(new GridLayout(1,3));
+	    button_pane.add(add_button);
+	    button_pane.add(replace_button);
+	    button_pane.add(remove_button);
+
+	    center_pane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(get("Editing_Controls")), BorderFactory.createEmptyBorder(2,2,2,2)));
+	    center_pane.setLayout(new BorderLayout());
+	    center_pane.add(selection_pane, BorderLayout.NORTH);
+	    center_pane.add(control_pane, BorderLayout.CENTER);
+	    center_pane.add(button_pane, BorderLayout.SOUTH);
 
 	    setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
 	    setLayout(new BorderLayout());
-	    add(header_pane, BorderLayout.NORTH);
-	    add(format_list_pane, BorderLayout.CENTER);
-	    add(control_pane, BorderLayout.SOUTH);
+	    add(instructions_pane, BorderLayout.NORTH);
+	    add(new JScrollPane(format_list), BorderLayout.CENTER);
+	    add(center_pane, BorderLayout.SOUTH);
 	    ready = true;
 	}
@@ -389,13 +394,15 @@
 	    // This is only necessary if the components have been realized
 	    if(ready) {
+		formats_changed = false;
 		model.refresh();
-		ArrayList feature_model = buildFeatureModel();
+		feature_model = buildFeatureModel();
 		// Remember the current selection
-		Object selected_object = feature.getSelectedItem();
-		feature.setModel(new DefaultComboBoxModel(feature_model.toArray()));
-		// Now resotre the selected object as best as possible
-		feature.setSelectedItem(selected_object);
-		if(instructions != null) {
-		    instructions.setCaretPosition(0);
+		Object selected_object = feature_combobox.getSelectedItem();
+		feature_combobox.setModel(new DefaultComboBoxModel(feature_model.toArray()));
+		// Now restore the selected object as best as possible
+		feature_combobox.setSelectedItem(selected_object);
+		selected_object = null;
+		if(instructions_textarea != null) {
+		    instructions_textarea.setCaretPosition(0);
 		}
 	    }   
@@ -408,87 +415,43 @@
 		Format format = (Format) model.getElementAt(i);
 		format.update();
-	    }
-	}
-
-	private ArrayList buildFeatureModel() {
-	    // Rebuild feature model.
-	    ArrayList feature_model = new ArrayList();
-	    // Add the set options
-	    for(int i = 0; i < Format.DEFAULT_FEATURES.length; i++) {
-		feature_model.add(new Entry(Format.DEFAULT_FEATURES[i]));
-	    }
-	    // Now the classifiers.
-	    for(int j = 0; j < CollectionDesignManager.classifier_manager.getSize(); j++) {
-		feature_model.add(new Entry(CollectionDesignManager.classifier_manager.getClassifier(j)));
-	    }
-	    Collections.sort(feature_model);
-	    return feature_model;
-	}
-
-	/** Formats the formatting string so that it contains safe characters and isn't enclosed in speech marks etc. (Ironic eh?)
-	 * @see java.lang.StringBuffer
-	 */
-	private String format(String raw) {
-	    String safe = null;
-	    if(raw != null && raw.length() > 0) {
-		StringBuffer temp = new StringBuffer(raw);
-		// Remove quotes at start and end. Look at my wiggly save three lines of code skills.
-		char start = ' ';
-		while(temp.length() > 0 && (start = temp.charAt(0)) == '\"' || start == '\'') {
-		    temp.delete(0, 1);
-		}
-		int length = 0;
-		char end = ' ';
-		while((length = temp.length()) > 0 && (end = temp.charAt(length - 1)) == '\"' || end == '\'') {
-		    temp.delete(length - 1, length);
-		}
-		// Now escape quotes within the format string
-		int quote_index = -1;
-		while((quote_index = temp.indexOf("\"", quote_index + 1)) != -1) {
-		    temp.replace(quote_index, quote_index + 1, "\\\"");
-		    quote_index = quote_index + 1;
-		}
-		// Done.
-		safe = temp.toString();
-	    }
-	    return safe;
-	}
-	/** Remove safe characters from string replacing them with unsafe ones.
-			* @see java.lang.StringBuffer
-			*/
-	private String unformat(String safe) {
-	    String raw = null;
-	    if(safe != null && safe.length() > 0) {
-		StringBuffer temp = new StringBuffer(safe);
-		int quote_index = -1;
-		while((quote_index = temp.indexOf("\\\"")) != -1) {
-		    temp.replace(quote_index, quote_index + 2, "\"");
-		}
-		raw = temp.toString();
-	    }
-	    return raw;
-	}
-
-	/** Listens for clicks on the add button, and if the relevant details are provided adds a new format. */
+		format = null;
+	    }
+
+	    // Now if the formats have changed, and the greenstone local library is being used and the collection has been built for previewing, then remove the add the collection to Greenstone to ensure the formatting updates correctly.
+	    if(formats_changed && Gatherer.c_man.built() && Gatherer.config.exec_file != null) {
+		// Release the collection
+		Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.RELEASE_COMMAND + Gatherer.c_man.getCollection().getName());
+		// Then re-add it to force format commands to be processed
+		Gatherer.g_man.preview_pane.configServer(GSDLSiteConfig.ADD_COMMAND + Gatherer.c_man.getCollection().getName());
+	    }
+	    formats_changed = false;
+	}
+
+	/** Listens for clicks on the add button, and if the relevant details are provided adds a new format. Note that formats are responsible for codecing the values into something that can be a) stored in a DOM and b) written to file */
 	private class AddListener
 	    implements ActionListener {
 	    public void actionPerformed(ActionEvent event) {
-		//ignore = true;
-		Entry entry = (Entry)feature.getSelectedItem();
+		ignore_event = true; // Prevent format_list excetera propagating events
+		Entry entry = (Entry)feature_combobox.getSelectedItem();
 		Object f = entry.getFeature();
-		String p = (String)part.getSelectedItem();
+		String p = (String)part_combobox.getSelectedItem();
+		Format format = null;
 		if(view_type.equals(FLAG)) {
-		    current_format = new Format(f, p, on.isSelected());
+		    format = new Format(f, p, enabled_checkbox.isSelected());
 		}
 		else {
-		    current_format = new Format(f, p, format(Utility.stripNL(editor.getText())));
-		}
-		addFormat(current_format);
-		add.setEnabled(false);
-		remove.setEnabled(true);
+		    format = new Format(f, p, editor_textarea.getText());
+		}
+		addFormat(format);
+		add_button.setEnabled(false);
+		replace_button.setEnabled(false);
+		remove_button.setEnabled(true);
 		// Update list selection
-		format_list.setSelectedValue(current_format, true);
-		new_entry = false;
-		//ignore = false;
+		format_list.setSelectedValue(format, true);
+		format = null;
+		p = null;
+		f = null;
+		entry = null;
+		ignore_event = false;
 	    }
 	}
@@ -510,82 +473,25 @@
 
 	    public void update() {
-		String safe = format(editor.getText());
-		if(!ignore && current_format != null) {
-		    // We have just performed an edit. Immediately update the format and model.
-		    if(safe != null) {
-			current_format.setValue(safe);
-		    }
-		    else {
-			current_format.setValue("");
-		    }
-		    Gatherer.c_man.configurationChanged();
-		    model.refresh(current_format);
-		}
-		Entry entry = (Entry) feature.getSelectedItem();
-		String name = entry.toString();
-		if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && safe != null && safe.length() != 0 && new_entry) {
-		    add.setEnabled(true);
+		// Determine if replace should be enabled
+		if(!format_list.isSelectionEmpty()) {
+		    Format format = (Format)format_list.getSelectedValue();
+		    replace_button.setEnabled(!format.isParamType() && editor_textarea.getText() != format.getValue());
 		}
 		else {
-		    add.setEnabled(false);
-		}
-	    }
-	}
-
-	/** This object provides a wrapping around an entry in the format target control, which is tranparent as to whether it is backed by a String or a Classifier. */
-	private class Entry
-	    implements Comparable {
-	    private Classifier classifier = null;
-	    private String text = null;
-	    public Entry(Object object) {
-		if(object instanceof Classifier) {
-		    classifier = (Classifier)object;
-		}
-		else if(object instanceof String) {
-		    text = (String)object;
-		}
-		else {
-		    text = "";
-		}
-	    }
-	    public Entry(String text) {
-		this.text = text;
-	    }
-	    public int compareTo(Object object) {
-		if(object == null) {
-		    return 1;
-		}
-		if(toString() == null) {
-		    return -1;
-		}
-		else {
-		    String object_str = object.toString();
-		    if(object_str == null) {
-			return 1;
-		    }
-		    return toString().compareTo(object_str);
-		}
-	    }
-	    public boolean equals(Object object) {
-		if(compareTo(object) == 0) {
-		    return true;
-		}
-		return false;
-	    }
-	    public Classifier getClassifier() {
-		return classifier;
-	    }
-	    public Object getFeature() {
-		if(classifier != null) {
-		    return classifier;
-		}
-		return text;
-	    }
-	    public String toString() {
-		if(classifier != null) {
-		    String name = classifier.toString();
-		    return name.substring(9);
-		}
-		return text;
+		    replace_button.setEnabled(false);
+		}
+	    }
+	}
+
+	private class EnabledListener
+	    implements ActionListener {
+	    
+	    public void actionPerformed(ActionEvent event) {
+		// If there is a current format selected, and the value of enable_checkbox is now different than to value in it, then enable to replace button.
+		if(!format_list.isSelectionEmpty()) {
+		    Format format = (Format)format_list.getSelectedValue();
+		    replace_button.setEnabled(format.isParamType() && enabled_checkbox.isSelected() != format.getState());
+		}
+		// Thats it. Add would have been enabled upon feature/part selection depending if no existing format, um, existed.
 	    }
 	}
@@ -594,30 +500,85 @@
 	    implements ActionListener {
 	    public void actionPerformed(ActionEvent event) {
-		if(!ignore) {
-		    current_format = null;
-		    Entry entry = (Entry) feature.getSelectedItem();
+		if(!ignore_event) {
+		    ignore_event = true;
+		    // Step one: reset part
+		    part_combobox.setSelectedIndex(0);
+		    // Step two: the rest
+		    Entry entry = (Entry) feature_combobox.getSelectedItem();
 		    String name = entry.toString();
 		    if(Format.isParamType(name)) {
 			// Flags first.
-			part.setEnabled(false);
-			part_pane.remove(part);
-			card_layout.show(view_pane, FLAG);
+			selection_pane.remove(part_pane);
+			card_layout.show(control_pane, FLAG);
 			view_type = FLAG;
-			add.setEnabled(true); // One of the options must be selected.
 		    }
 		    else {
-			part.setEnabled(true);
-			part_pane.add(part, BorderLayout.CENTER);
-			card_layout.show(view_pane, CUSTOM);
-			view_type = CUSTOM;
-			if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) {
-			    add.setEnabled(true);
+			selection_pane.add(part_pane);
+			card_layout.show(control_pane, VALUE);
+			view_type = VALUE;
+		    }
+		    control_pane.updateUI();
+		    // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if itsa already in the model
+		    Object f = entry.getFeature();
+		    String p = (String)part_combobox.getSelectedItem();
+		    // You can never add anything to blank-blank
+		    if(f.toString().length() == 0 && p.length() == 0) {
+			add_button.setEnabled(false);
+			replace_button.setEnabled(false);
+			remove_button.setEnabled(false);
+		    }
+		    else {
+			name = Format.generateName(f, p);
+			Format format = getFormat(name);
+			// If there is an existing feature, select it.
+			if(format != null) {
+			    format_list.setSelectedValue(format, true);
+			    // Now use type to determine what controls are visible, and what have initial values.
+			    if(format.isParamType()) {
+				// Flags first.
+				selection_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(format.getState());
+			    }
+			    else {
+				selection_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+				editor_textarea.setText(format.getValue());
+			    }
+			    control_pane.updateUI();
+			remove_button.setEnabled(true);
 			}
 			else {
-			    add.setEnabled(false);
+			    format_list.clearSelection();
+			    if(Format.isParamType(name)) {
+				// Flags first.
+				selection_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(false);
+			    }
+			    else {
+				selection_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+				editor_textarea.setText("");
+			    }
+			    add_button.setEnabled(true);
 			}
+			format = null;
+			name = null;
 		    }
-		    control_pane.updateUI();
-		    new_entry = true;
+		    p = null;
+		    f = null;
+		    replace_button.setEnabled(false);
+		    name = null;
+		    entry = null;
+		    ignore_event = false;
 		}
 	    }
@@ -627,95 +588,138 @@
 	    implements ListSelectionListener {
 	    public void valueChanged(ListSelectionEvent event) {
-		if(!ignore) {
+		if(!ignore_event) {
 		    if(!format_list.isSelectionEmpty()) {
-			ignore = true;
-			current_format = (Format)format_list.getSelectedValue();
+			ignore_event = true;
+			Format format = (Format)format_list.getSelectedValue();
 			// Try to match the target, remembering the entries within are Entry's
-			Entry an_entry = new Entry(current_format.getFeature());
-			feature.setSelectedItem(an_entry);
+			Entry an_entry = new Entry(format.getFeature());
+			feature_combobox.setSelectedItem(an_entry);
 			// If we didn't match anything, add it and select it again
-			Entry result_entry = (Entry) feature.getSelectedItem();
+			Entry result_entry = (Entry) feature_combobox.getSelectedItem();
 			if(!an_entry.equals(result_entry)) {
-			    feature.insertItemAt(an_entry, feature.getItemCount());
-			    feature.setSelectedItem(an_entry);
+			    feature_combobox.insertItemAt(an_entry, feature_combobox.getItemCount());
+			    feature_combobox.setSelectedItem(an_entry);
 			}
 			
-			if(current_format.canHavePart()) {
-			    part.setEnabled(true);
+			if(format.canHavePart()) {
+			    part_combobox.setEnabled(true);
 			    // Try to match the part.
-			    String part_entry = current_format.getPart();
-			    part.setSelectedItem(part_entry);
+			    String part_entry = format.getPart();
+			    part_combobox.setSelectedItem(part_entry);
 			    // If we didn't match anything, add it and select it again
-			    String selected_part = (String)part.getSelectedItem();
+			    String selected_part = (String)part_combobox.getSelectedItem();
 			    if(!part_entry.equals(selected_part)) {
-				part.insertItemAt(part_entry, part.getItemCount());
-				feature.setSelectedItem(part_entry);
+				part_combobox.insertItemAt(part_entry, part_combobox.getItemCount());
+				part_combobox.setSelectedItem(part_entry);
 			    }
 			}
 			else {
-			    part.setEnabled(false);
+			    part_combobox.setEnabled(false);
 			}
 			// Now use type to determine what controls are visible, and what have initial values.
-			if(current_format.isParamType()) {
+			if(format.isParamType()) {
 			    // Flags first.
-			    part.setEnabled(false);
-			    part_pane.remove(part);
-			    card_layout.show(view_pane, FLAG);
+			    selection_pane.remove(part_pane);
+			    card_layout.show(control_pane, FLAG);
 			    view_type = FLAG;
 			    // Initial value
-			    on.setSelected(current_format.getState());
-			    off.setSelected(!current_format.getState());
-			    add.setEnabled(false); // Can only update
+			    enabled_checkbox.setSelected(format.getState());
 			}
 			else {
-			    part.setEnabled(true);
-			    part_pane.add(part, BorderLayout.CENTER);
-			    card_layout.show(view_pane, CUSTOM);
-			    view_type = CUSTOM;
+			    selection_pane.add(part_pane);
+			    card_layout.show(control_pane, VALUE);
+			    view_type = VALUE;
 			    // Initial value
-			    editor.setText(unformat(current_format.getValue()));
-			    add.setEnabled(false);
+			    editor_textarea.setText(format.getValue());
 			}
 			control_pane.updateUI();
-			ignore = false;
-			preview.setEnabled(true);
-			remove.setEnabled(true);
-			new_entry = false;
+			remove_button.setEnabled(true);
+			ignore_event = false;
 		    }
 		    else {
-			preview.setEnabled(false);
-			remove.setEnabled(false);
+			remove_button.setEnabled(false);
 		    }
-		}
-	    }
-	}
+		    add_button.setEnabled(false);
+		    replace_button.setEnabled(false);
+		}
+	    }
+	}
+
 	private class InsertListener
 	    implements ActionListener {
 	    public void actionPerformed(ActionEvent event) {
-		editor.insert((String)special.getSelectedItem(), editor.getCaretPosition());
-	    }
-	}
+		editor_textarea.insert((String)variable_combobox.getSelectedItem(), editor_textarea.getCaretPosition());
+	    }
+	}
+
 	private class PartListener
 	    implements ActionListener {
 	    public void actionPerformed(ActionEvent event) {
-		if(!ignore) {
-		    current_format = null;
-		    Entry entry = (Entry) feature.getSelectedItem();
-		    String name = entry.toString();
-		    if(!(name.length() == 0 && ((String)part.getSelectedItem()).length() == 0) && editor.getText().length() != 0) {
-			add.setEnabled(true);
+		if(!ignore_event) {
+		    // Add is only enabled if there isn't already a format for the choosen feature and part. Create a dummy format and test if itsa already in the model
+		    Entry entry = (Entry) feature_combobox.getSelectedItem();
+		    Object f = entry.getFeature();
+		    String p = (String)part_combobox.getSelectedItem();
+		    // You can never add anything to blank-blank
+		    if(f.toString().length() == 0 && p.length() == 0) {
+			add_button.setEnabled(false);
+			replace_button.setEnabled(false);
+			remove_button.setEnabled(false);
 		    }
 		    else {
-			add.setEnabled(false);
+			String name = Format.generateName(f, p);
+			Format format = getFormat(name);
+			// If there is an existing feature, select it.
+			if(format != null) {
+			    format_list.setSelectedValue(format, true);
+			    // Now use type to determine what controls are visible, and what have initial values.
+			    if(format.isParamType()) {
+				// Flags first.
+				selection_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(format.getState());
+			    }
+			    else {
+				selection_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+				editor_textarea.setText(format.getValue());
+			    }
+			    control_pane.updateUI();
+			    remove_button.setEnabled(true);
+			}
+			else {
+			    format_list.clearSelection();
+			    if(Format.isParamType(name)) {
+				// Flags first.
+				selection_pane.remove(part_pane);
+				card_layout.show(control_pane, FLAG);
+				view_type = FLAG;
+				// Initial value
+				enabled_checkbox.setSelected(false);
+			    }
+			    else {
+				selection_pane.add(part_pane);
+				card_layout.show(control_pane, VALUE);
+				view_type = VALUE;
+				// Initial value
+				editor_textarea.setText("");
+			    }
+			    add_button.setEnabled(true);
+			}
+			format = null;
+			name = null;
 		    }
-		    new_entry = true;
-		}
-	    }
-	}
-	private class PreviewListener
-	    implements ActionListener {
-	    public void actionPerformed(ActionEvent event) {
-	    }
-	}
+		    p = null;
+		    f = null;
+		    entry = null;
+		    replace_button.setEnabled(false);
+		}
+	    }
+	}
+
 	private class RemoveListener
 	    implements ActionListener {
@@ -724,28 +728,90 @@
 		    removeFormat((Format)format_list.getSelectedValue());
 		    // Change buttons
-		    add.setEnabled(true);
-		    remove.setEnabled(false);
-		}
-	    }
-	}
-	private class StateListener
+		    add_button.setEnabled(true);
+		    replace_button.setEnabled(false);
+		}
+		remove_button.setEnabled(false);
+	    }
+	}
+
+	private class ReplaceListener
 	    implements ActionListener {
+
 	    public void actionPerformed(ActionEvent event) {
-		if(!ignore && current_format != null) {
-		    // We have just performed an edit. Immediately update the format and model.
-		    current_format.setState(on.isSelected());
-		    model.refresh(current_format);
-		}
-	    }
-	}
-	private class ValueListener
-	    extends KeyAdapter {
-	    public void keyReleased(KeyEvent event) {
-		if(!ignore && current_format != null) {
-		    // We have just performed an edit. Immediately update the format and model.
-		    current_format.setValue(value.getText());
-		    model.refresh(current_format);
-		}
-	    }
+		/** @todo **/
+	    }
+	}
+
+	private class ResetListener
+	    implements ActionListener {
+
+	    public void actionPerformed(ActionEvent event) {
+		/** @todo **/
+	    }
+	}
+    }
+
+    /** This object provides a wrapping around an entry in the format target control, which is tranparent as to whether it is backed by a String or a Classifier. */
+    private class Entry
+	implements Comparable {
+	private Classifier classifier = null;
+	private String text = null;
+	
+	public Entry(Object object) {
+	    if(object instanceof Classifier) {
+		classifier = (Classifier)object;
+	    }
+	    else if(object instanceof String) {
+		text = (String)object;
+	    }
+	    else {
+		text = "";
+	    }
+	}
+	
+	public Entry(String text) {
+	    this.text = text;
+	}
+	
+	public int compareTo(Object object) {
+	    if(object == null) {
+		return 1;
+	    }
+	    if(toString() == null) {
+		return -1;
+	    }
+	    else {
+		String object_str = object.toString();
+		if(object_str == null) {
+		    return 1;
+		}
+		return toString().compareTo(object_str);
+	    }
+	}
+	
+	public boolean equals(Object object) {
+	    if(compareTo(object) == 0) {
+		return true;
+	    }
+	    return false;
+	}
+	
+	public Classifier getClassifier() {
+	    return classifier;
+	}
+	
+	public Object getFeature() {
+	    if(classifier != null) {
+		return classifier;
+	    }
+	    return text;
+	}
+	
+	public String toString() {
+	    if(classifier != null) {
+		// Return the classifier - less the 'classify ' prefix
+		return classifier.toString().substring(9);
+	    }
+	    return text;
 	}
     }
