package org.osm2world.viewer.view;
import static java.lang.Math.min;
import static java.util.Arrays.sort;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.prefs.BackingStoreException;
import java.util.prefs.PreferenceChangeEvent;
import java.util.prefs.PreferenceChangeListener;
import java.util.prefs.Preferences;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import org.osm2world.viewer.Viewer;
import com.google.common.base.Function;
/**
* keeps a "recent files" menu current based on a persistently stored list
*/
public class RecentFilesUpdater implements PreferenceChangeListener {
private static final int MAX_ENTRIES = 10;
private final JMenu recentFilesMenu;
private final Function<File, ActionListener> actionForFile;
/**
* creates the updater, registers it as a listener
* and builds the initial content of the menu
*
* @param actionForFile
* function creating the listener for opening a particular file
*/
public RecentFilesUpdater(JMenu recentFilesMenu,
Function<File, ActionListener> actionForFile) {
this.recentFilesMenu = recentFilesMenu;
this.actionForFile = actionForFile;
prefs().addPreferenceChangeListener(this);
updateRecentFilesMenu();
}
@Override
public void preferenceChange(PreferenceChangeEvent e) {
updateRecentFilesMenu();
}
/**
* builds (or rebuilds) the menu items in the {@link #recentFilesMenu}
* based on the current state of the preferences
*/
private void updateRecentFilesMenu() {
recentFilesMenu.removeAll();
try {
for (File file : fileListFromPrefs()) {
JMenuItem menuItem = new JMenuItem(file.getName());
menuItem.addActionListener(actionForFile.apply(file));
recentFilesMenu.add(menuItem);
}
} catch (BackingStoreException e) {
e.printStackTrace();
}
recentFilesMenu.setEnabled(recentFilesMenu.getItemCount() > 0);
}
/**
* returns the {@link Preferences} node used to persistently store the
* recent files list
*/
private static final Preferences prefs() {
return Preferences.userNodeForPackage(Viewer.class).node("recentFiles");
}
/**
* returns the list of recent files from user preferences.
* The list is sorted from newest to oldest entry.
*/
private static final List<File> fileListFromPrefs()
throws BackingStoreException {
List<File> result = new ArrayList<File>();
String[] keys = prefs().keys();
sort(keys);
for (int i = 0; i < keys.length; i++) {
String pathname = prefs().get(keys[i], null);
result.add(new File(pathname));
}
return result;
}
/**
* adds a file to the persistently stored list of recent files.
* May replace an existing entry if maximum capacity is reached.
*/
public static void addRecentFile(File newFile) {
newFile = newFile.getAbsoluteFile();
try {
List<File> files = fileListFromPrefs();
files.remove(newFile);
files.add(0, newFile);
prefs().clear();
for (int i = 0; i < min(files.size(), MAX_ENTRIES); i++) {
prefs().put("entry_" + (char)('a' + i),
files.get(i).getAbsolutePath());
}
} catch (BackingStoreException e) {
e.printStackTrace();
}
}
}