package org.freehep.swing;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.Properties;
import java.util.Vector;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.event.EventListenerList;

/**
 * A class for maintaining a "Recent File List".
 * The recent file list can be stored between program invocations in
 * a properties file. One or more RecentFileLists can easily
 * be embedded in a JMenu.
 *
 * @author Tony Johnson (tonyj@slac.stanford.edu)
 * @version $Id: RecentFileList.java 8584 2006-08-10 23:06:37Z duns $
 */
public class RecentFileList implements ActionListener
{
	/**
	 * Create a RecentFileList
	 */
	public RecentFileList()
	{
		this(null);
	}
	/**
	 * Create a RecentFileList with a given maximum length
	 * @param size the maximum number of files to remember
	 */
	public RecentFileList(int size)
	{
		this(null,size);
	}
	/**
	 * Create a recent file list. The type parameter is used to
	 * prefix entries in the properties file, so that multiple
	 * RecentFileLists can be used in an application.
	 * @param type The prefix to use
	 */
	public RecentFileList(String type)
	{
		this(type,4);
	}
	/**
	 * Create a recent file list with a given type and size
	 * @param type The prefix to use
	 * @param size the maximum number of files to remember
	 */
	public RecentFileList(String type, int size)
	{
		files = new Vector(size);
		this.size = size;
		this.type = type;
		used = 0;
	}
	public void addActionListener(ActionListener l)
	{
		listenerList.add(ActionListener.class, l);
	}
	public void removeActionListener(ActionListener l)
	{
		listenerList.remove(ActionListener.class, l);
	}
	/**
	 * An action event is fired when the user selects one of the
	 * files from a menu. The "actionCommand" in the event will be
	 * set to the name of the selected file.
	 */
	protected void fireActionPerformed(ActionEvent e)
	{
		// Guaranteed to return a non-null array
		Object[] listeners = listenerList.getListenerList();
		// Process the listeners last to first, notifying
		// those that are interested in this event
		for (int i = listeners.length-2; i>=0; i-=2)
		{
			if (listeners[i]==ActionListener.class)
			{
				((ActionListener)listeners[i+1]).actionPerformed(e);
			}
		}
	}
	public void actionPerformed(ActionEvent e)
	{
		fireActionPerformed(e);
	}
	/**
	 * Save the recent file list in a Properties set
	 * @param props The Properties set to save the files in
	 */
	public void save(Properties props)
	{
		String key = "RecentFile_" + (type!=null ? type+"_" : "" );
		for (int i=0; i<used; i++)
		{
			props.put(key+i,files.elementAt(i).toString());
		}
		props.put(key+"Used",String.valueOf(used));
	}
	/**
	 * Load the recent file list from a Properties set
	 * @param props The Properties set to load from
	 */
	public void load(Properties props)
	{
		String key = "RecentFile_" + (type!=null ? type+"_" : "" );
		files.removeAllElements();
		used = Integer.parseInt(props.getProperty(key+"Used","0"));
		for (int i=0; i<used; i++)
		{
			String value = props.getProperty(key+i);
			if (value == null) break;
			files.addElement(value);
		}
	}
	/**
	 * Add a file to the list
	 * @param f The file to add
	 */
	public void add(File f)
	{
		try
		{
			add(f.getCanonicalPath());
		}
		catch (java.io.IOException x)
		{
			add(f.getAbsolutePath());
		}
	}
	/**
	 * Remove a file from the list
	 * @param f Remove a file from the list
	 */
	public void remove(File f)
	{
		remove(f.getName());
	}
	/**
	 * Add a file to the list
	 * @param name The name of the file to add
	 */
	public void add(String name)
	{
		int pos = files.indexOf(name);
		if (pos > 0)
		{
			files.removeElementAt(pos);
			files.insertElementAt(name,0);
		}
		else if (pos != 0)
		{
			if (used == size) files.removeElementAt(size-1);
			else used++;
			files.insertElementAt(name,0);
		}
	}
	/**
	 * Remove a file from the list
	 * @param name The name of the file to remove
	 */
	public void remove(String name)
	{
		if (files.removeElement(name)) used--;
	}
	/**
	 * Adds the recent file list to a menu.
	 * The files will be added at the end of the menu, with a
	 * separator before the files (if there are >0 files in the list)
	 */
	public void buildMenu(JMenu menu)
	{
		if (used > 0)
		{
			menu.addSeparator();
			for (int i=0; i<used; i++)
			{
				JMenuItem item = new JMenuItem(String.valueOf(i+1)+" "+files.elementAt(i));
				item.setActionCommand(files.elementAt(i).toString());
				if (size<9) item.setMnemonic(Character.forDigit(i+1,10));
				item.addActionListener(this);
				menu.add(item);
			}
		}
	}
	private Vector files;
	private String type;
	private int size;
	private int used;
	private EventListenerList listenerList = new EventListenerList();
}
