Index: gli/trunk/src/org/greenstone/gatherer/gui/URLField.java
===================================================================
--- gli/trunk/src/org/greenstone/gatherer/gui/URLField.java	(revision 16337)
+++ gli/trunk/src/org/greenstone/gatherer/gui/URLField.java	(revision 16338)
@@ -4,20 +4,62 @@
 import java.net.*;
 import javax.swing.*;
-
-
+import java.util.*;
+import java.io.*;
+import org.greenstone.gatherer.Gatherer;
+import org.greenstone.gatherer.Configuration;
+
+/** Modified. 
+ * Class used by WarningDialog and Gatherer which represents a textual input control 
+ * (TextField or Combobox) into which a URL can be entered. Provides some static methods
+ * shared by these controls and by a general JTextField control which can all be used 
+ * in a WarningDialog. Class URLField also contains an inner Interface class and two 
+ * static inner classes that implement this interface: Text and DropDown. 
+ * Finally, another static inner class URLCollectionPair associates each Gliserver URL
+ * (or Library URL) that can be displayed in the DropDown with the last opened collection
+ * file for the Greenstone server at that URL. 
+*/
 public class URLField
-    extends JTextField
 {
-    public URLField(Color foreground, Color background)
-    {
-	super();
-	setBackground(background);
-	setForeground(foreground);
-    }
-
-
-    public boolean validateURL()
-    {
-	String url_string = getText();
+    static public String getText(JComponent control)
+    {
+	if(control instanceof JTextField) { // not specifically a URL Field, therefore, we're not meant to do checking
+	    return ((JTextField)control).getText();
+	} 
+	else if(control instanceof URLField.DropDown) {
+	    return (String)((JComboBox)control).getSelectedItem();
+	}
+
+	// unknown control, shouldn't happen
+	return "";
+    }
+
+    static public String setText(JComponent control, String text)
+    {
+	if(control instanceof JTextField) { // not specifically a URL Field, therefore, we're not meant to do checking
+	    ((JTextField)control).setText(text);
+	} 
+	else if(control instanceof URLField.DropDown) {
+	    ((JComboBox)control).setSelectedItem(text);	    
+	}
+
+	// unknown control, shouldn't happen
+	return "";
+    }
+
+    static public boolean validateURL(JComponent control)
+    {
+	if(control instanceof URLField.Text) {
+	    return ((URLField.Text)control).validateURL();
+	} 
+	else if (control instanceof JTextField) {
+	    return true; // not specifically a URL Field, therefore, we're not meant to do checking
+	}
+	else { // control is a DropDown
+	    return ((URLField.DropDown)control).validateURL();
+	}
+    }
+
+    static public boolean validateURL(String url_string)
+    {
 	if (!url_string.equals("")) {
 	    // Check the URL string is valid by trying to create a URL object from it
@@ -34,3 +76,237 @@
 	return true;
     }
+
+    static public void store(JComponent control, String affected_property) {
+	if(control instanceof JTextField) { 
+	    String value = ((JTextField)control).getText();
+	    Configuration.setString(affected_property, true, value);
+	} 
+	else { // DropDown
+	    ((DropDown)control).saveProperties();
+	}
+    }
+
+    
+    /** INTERFACE CLASS IMPLEMENTED BY Static inner classes Text and DropDown */
+    public static interface URLFieldControl {
+	public boolean validateURL();
+    }
+
+
+    /** STATIC INNER CLASS URLTextField */
+    public static class Text 
+	extends JTextField implements URLFieldControl 
+    {
+	public Text(Color foreground, Color background)
+	{
+	    super();
+	    setBackground(background);
+	    setForeground(foreground);
+	}
+
+	public boolean validateURL() {
+	    String url_string = getText();
+	    return URLField.validateURL(url_string);
+	}
+    }
+
+   
+    /** STATIC INNER CLASS DropDown, an editable URLComboBox */
+    public static class DropDown 
+	extends JComboBox implements URLFieldControl
+    {
+	private String checkString = null; // optional string to check the URLs items against to see whether the URLs contain this
+	private String affectedProperty = null; // the Configuration property associated with this DropDown
+	private String coaffectedProperty = null; // the Configuration property whose suffix should change along with the affectedProperty
+	
+	private static final int MAX_URLS = 5;
+
+	public DropDown(Color foreground, Color background, String[] defaultURLs, 
+			String affectedProperty, String coaffectedProperty)
+	{
+	    super(URLCollectionPair.createDefaultsArray(defaultURLs));
+	    this.setEditable(true);
+	    this.getEditor().selectAll();
+	    
+	    setBackground(background);
+	    setForeground(foreground);
+	    
+	    this.affectedProperty = affectedProperty;
+	    this.coaffectedProperty = coaffectedProperty;
+	    // read any URLS specified in the config file
+	    setComboBoxValues();
+	    
+	}
+
+	public DropDown(Color foreground, Color background, String[] defaultURLs, 
+			String affectedProperty, String coaffectedProperty, String checkString)
+	{
+	    this(foreground, background, defaultURLs, affectedProperty, coaffectedProperty);
+	    this.checkString = checkString;
+	}	
+
+	public boolean validateURL() {
+	    //String url_string = (String)this.getEditor().getItem();
+	    String url_string = this.getSelectedItem().toString(); // returns url of the combobox item
+		
+	    if(checkString != null && !url_string.endsWith(checkString)) {
+		return false;
+	    } else {
+		return URLField.validateURL(url_string);
+	    }
+	}
+
+	public void saveProperties() {
+	    // 1. Add the first url just edited (if any) 
+
+	    // The user might have created a new STRING, or selected an existing URLCollectionPair
+	    // We don't know the type!
+	    Object o = this.getSelectedItem(); 
+	    URLCollectionPair editedItem = (o instanceof URLCollectionPair) 
+		? (URLCollectionPair)o : new URLCollectionPair(o.toString());
+	    	    
+	    if(editedItem != null) {
+		insertItemAt(editedItem, 0);
+	    } else {
+		editedItem = (URLCollectionPair)getItemAt(0); // else reuse the first default:
+	    }
+	    Configuration.setString(affectedProperty, true, editedItem.getURL());
+	    
+	    // concurrently set the last opened collection for this url
+	    String lastOpenedCollection = editedItem.getCollection();
+	    if(lastOpenedCollection.equals("")) {
+		Configuration.setString(coaffectedProperty, true, null);
+	    } else {
+		Configuration.setString(coaffectedProperty, true, lastOpenedCollection);
+	    }
+
+
+	    // 2. Add the remaining urls into the combobox
+	    int url_count = 1; // remain under MAX_URLS AND under the number of actual URLs in the dropdown
+	    for(int i = 0; url_count < MAX_URLS && i < getItemCount(); i++, url_count++) {
+		
+		URLCollectionPair item = (URLCollectionPair)getItemAt(i);
+		String url = item.getURL();
+		
+		if(item == null || url.equals(editedItem.getURL()) || url.equals("")) { 
+		    // skip any duplicates of the just-edited URL and skip empty URLs
+		    url_count--;
+		} 
+		else { 
+		    Configuration.setString(affectedProperty+url_count, true, url);
+		    
+		    // concurrently save the name of the corresponding open collection
+		    if(item.getCollection().equals("")) {
+			Configuration.setString(coaffectedProperty+url_count, true, null);
+		    } else {
+			Configuration.setString(coaffectedProperty+url_count, true, item.getCollection());
+		    }
+
+		} // else retain old value for this affectedProperty (general.gliserver_url)
+	    }
+	    Configuration.save();
+	}
+
+	
+	// Get values from Configuration file, or (if none) use defaultURLs.
+	// Put them into the combobox
+	private void setComboBoxValues() {
+
+	    String url = Configuration.getString(affectedProperty, true);
+	    String collection = Configuration.getString(coaffectedProperty, true);
+	    boolean finished = url.equals("");
+	    if(!finished) {
+		this.removeAllItems(); // remove defaults, since config file now contains init values
+		this.addItem(new URLCollectionPair(url, collection));
+	    } // else urls and combobox already contains the defaults
+	   	    
+
+	    for(int i = 1; !finished; i++) {
+		url = Configuration.getString(affectedProperty+i, true);
+		collection = Configuration.getString(coaffectedProperty+i, true);
+		if(url.equals("")) {
+		    finished = true;
+		}
+		else { // url is not empty
+		    this.addItem(new URLCollectionPair(url, collection));
+		}
+	    }
+	    
+	    // setting the size of the dropdown control
+	    Dimension newSize=new Dimension(getPreferredSize().width+20, getPreferredSize().height);
+	    setPreferredSize(newSize);
+	}
+    }
+
+
+    /** STATIC INNER CLASS URLCollectionPair. 
+     * Since the configuration for a (remote) Greenstone2 and Greenstone3 is now
+     * stored in a single file for both, we can have GLI connecting to different servers 
+     * while for each server, a different collection may have been left open last time.
+     * This class URLCollectionPair will associate a GLIServer_URL or Library_URL with
+     * the last opened collection file for it. It is used by URLField.DropDown combobox. */
+    public static class URLCollectionPair {
+	String url;        // gliserverURL 
+	String collection; // last opened collection for the corresponding gliserver
+
+	
+	public static URLCollectionPair[] createDefaultsArray(String[] defaultURLs) {
+	    URLCollectionPair[] pairs = new URLCollectionPair[defaultURLs.length];
+	    for(int i = 0; i < pairs.length; i++) {
+		pairs[i] = new URLCollectionPair(defaultURLs[i]); // no associated open collection
+	    }
+	    return pairs;
+	}
+
+	public URLCollectionPair(String url) {
+	    this.set(url, "");
+	}
+
+	public URLCollectionPair(String url, String collection) {
+	    this.set(url, collection);
+	}
+
+	public void set(String url, String collection) {
+	    this.url = url;
+	    this.collection = collection;
+	}
+
+	public void setURL(String url) {
+	    this.url = url;
+	}
+
+	public void setCollection(String collection) {
+	    this.collection = collection;
+	}
+
+	public String getCollection() {
+	    return collection;
+	}
+
+	public String getURL() {
+	    return url;
+	}
+
+	/** For display in comboboxes */
+	public String toString() {
+	    return url;
+	}
+
+	/** @returns the number that is suffixed to the gliserver_url */
+	public String getSuffixNumber() {
+	    String numericSuffix = "";
+	    boolean stop = false;
+	    for(int index = url.length()-1; index >= 0 && !stop; index--) { // work from the end
+		char character = url.charAt(index);
+		if(Character.isDigit(character)) {
+		    numericSuffix = Character.toString(character) + numericSuffix;
+		} else {
+		    stop = true;
+		}
+	    }
+
+	    return numericSuffix;
+	}
+    }
+
 }
