* improved preferences handling

* SelectButton refactoring
This commit is contained in:
Reinhard Pointner 2008-02-29 01:16:52 +00:00
parent 36c0406ec6
commit 3a91757e3e
12 changed files with 237 additions and 126 deletions

View File

@ -4,9 +4,12 @@ package net.sourceforge.filebot;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
@ -14,6 +17,10 @@ public class Settings {
private static Settings settings = new Settings(); private static Settings settings = new Settings();
public static final String SELECTED_PANEL = "panel";
public static final String SEARCH_HISTORY = "history/search";
public static final String SUBTITLE_HISTORY = "history/subtitle";
public static Settings getSettings() { public static Settings getSettings() {
return settings; return settings;
@ -23,74 +30,91 @@ public class Settings {
private Settings() { private Settings() {
this.prefs = Preferences.userNodeForPackage(this.getClass()); this.prefs = Preferences.userRoot().node("filebot");
}
private String defaultDelimiter = ";";
private void putStringList(String key, Collection<String> values) {
try {
StringBuffer sb = new StringBuffer();
for (String value : values) {
sb.append(value.replaceAll(defaultDelimiter, " "));
sb.append(defaultDelimiter);
}
prefs.put(key, sb.toString());
} catch (IllegalArgumentException e) {
// value might exceed max length
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString());
}
} }
private Collection<String> getStringList(String key) { public void putString(String key, String value) {
String[] values = prefs.get(key, "").split(defaultDelimiter); prefs.put(key, value);
}
public String getString(String key, String def) {
return prefs.get(key, def);
}
public void putInt(String key, int value) {
prefs.putInt(key, value);
}
public int getInt(String key, int def) {
return prefs.getInt(key, def);
}
public void putBoolean(String key, boolean value) {
prefs.putBoolean(key, value);
}
public boolean getBoolean(String key, boolean def) {
return prefs.getBoolean(key, def);
}
public Collection<String> getStringList(String key) {
Preferences listNode = prefs.node(key);
List<String> list = new ArrayList<String>(); List<String> list = new ArrayList<String>();
for (String value : values) { try {
if (!value.isEmpty()) for (String nodeKey : listNode.keys()) {
list.add(value); list.add(listNode.get(nodeKey, null));
}
} catch (BackingStoreException e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString());
} }
return list; return list;
} }
private static enum Key { public void putStringList(String key, Collection<String> list) {
panel, tvshowcompletionterms, subtitlecompletionterms; Preferences listNode = prefs.node(key);
int i = 0;
for (String entry : list) {
listNode.put(Integer.toString(i), entry);
i++;
}
} }
public int getSelectedPanel() { public Map<String, String> getStringMap(String key) {
return prefs.getInt(Key.panel.name(), 3); Preferences mapNode = prefs.node(key);
Map<String, String> map = new HashMap<String, String>();
try {
for (String mapNodeKey : mapNode.keys()) {
map.put(mapNodeKey, mapNode.get(mapNodeKey, null));
}
} catch (BackingStoreException e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString());
}
return map;
} }
public void setSelectedPanel(int index) { public void putStringMap(String key, Map<String, String> map) {
prefs.putInt(Key.panel.name(), index); Preferences mapNode = prefs.node(key);
for (Map.Entry<String, String> entry : map.entrySet()) {
mapNode.put(entry.getKey(), entry.getValue());
} }
public void setTvShowCompletionTerms(Collection<String> terms) {
putStringList(Key.tvshowcompletionterms.name(), terms);
}
public Collection<String> getTvShowCompletionTerms() {
return getStringList(Key.tvshowcompletionterms.name());
}
public void setSubtitleCompletionTerms(Collection<String> terms) {
putStringList(Key.subtitlecompletionterms.name(), terms);
}
public Collection<String> getSubtitleCompletionTerms() {
return getStringList(Key.subtitlecompletionterms.name());
} }
} }

View File

@ -6,6 +6,8 @@ import java.awt.Image;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@ -27,8 +29,10 @@ public class ResourceManager {
try { try {
return ImageIO.read(getResource(name)); return ImageIO.read(getResource(name));
} catch (IOException e) { } catch (IOException e) {
return null; Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString());
} }
return null;
} }
@ -37,6 +41,11 @@ public class ResourceManager {
} }
public static ImageIcon getFlagIcon(String countryCode) {
return new ImageIcon(ResourceManager.class.getResource(String.format("flags/%s.gif", countryCode)));
}
private static URL getResource(String name) { private static URL getResource(String name) {
String resource = null; String resource = null;

View File

@ -57,7 +57,7 @@ public class FileBotWindow extends JFrame implements ListSelectionListener {
setSize(760, 615); setSize(760, 615);
selectionListPanel.setSelectedIndex(Settings.getSettings().getSelectedPanel()); selectionListPanel.setSelectedIndex(Settings.getSettings().getInt(Settings.SELECTED_PANEL, 3));
} }
@ -71,7 +71,7 @@ public class FileBotWindow extends JFrame implements ListSelectionListener {
JComponent c = (JComponent) getContentPane(); JComponent c = (JComponent) getContentPane();
c.updateUI(); c.updateUI();
Settings.getSettings().setSelectedPanel(selectionListPanel.getSelectedIndex()); Settings.getSettings().putInt(Settings.SELECTED_PANEL, selectionListPanel.getSelectedIndex());
} }

View File

@ -20,6 +20,8 @@ class RenameListCellRenderer extends FancyListCellRenderer {
public RenameListCellRenderer(ListModel names, ListModel files) { public RenameListCellRenderer(ListModel names, ListModel files) {
this.names = names; this.names = names;
this.files = files; this.files = files;
setHighlightingEnabled(false);
} }
private Color noMatchGradientBeginColor = Color.decode("#B7B7B7"); private Color noMatchGradientBeginColor = Color.decode("#B7B7B7");
@ -44,7 +46,7 @@ class RenameListCellRenderer extends FancyListCellRenderer {
private int getMinLength() { private int getMinLength() {
if (names == null || files == null) if ((names == null) || (files == null))
return 0; return 0;
int n1 = names.getSize(); int n1 = names.getSize();

View File

@ -12,7 +12,6 @@ import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -21,7 +20,6 @@ import javax.swing.AbstractAction;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Box; import javax.swing.Box;
import javax.swing.DefaultListModel; import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JScrollPane; import javax.swing.JScrollPane;
@ -41,11 +39,8 @@ import net.sourceforge.filebot.ui.FileBotList;
import net.sourceforge.filebot.ui.FileBotPanel; import net.sourceforge.filebot.ui.FileBotPanel;
import net.sourceforge.filebot.ui.MessageManager; import net.sourceforge.filebot.ui.MessageManager;
import net.sourceforge.filebot.ui.transfer.SaveAction; import net.sourceforge.filebot.ui.transfer.SaveAction;
import net.sourceforge.filebot.web.AnidbClient;
import net.sourceforge.filebot.web.Episode; import net.sourceforge.filebot.web.Episode;
import net.sourceforge.filebot.web.EpisodeListClient; import net.sourceforge.filebot.web.EpisodeListClient;
import net.sourceforge.filebot.web.TVRageClient;
import net.sourceforge.filebot.web.TvdotcomClient;
import net.sourceforge.tuned.ui.SelectButton; import net.sourceforge.tuned.ui.SelectButton;
import net.sourceforge.tuned.ui.SelectDialog; import net.sourceforge.tuned.ui.SelectDialog;
import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter; import net.sourceforge.tuned.ui.SwingWorkerPropertyChangeAdapter;
@ -65,30 +60,24 @@ public class SearchPanel extends FileBotPanel {
private TextCompletion searchFieldCompletion; private TextCompletion searchFieldCompletion;
private List<EpisodeListClient> episodeListClients = new ArrayList<EpisodeListClient>();
private JSpinner seasonSpinner; private JSpinner seasonSpinner;
public SearchPanel() { public SearchPanel() {
super("Search", ResourceManager.getIcon("panel.search")); super("Search", ResourceManager.getIcon("panel.search"));
episodeListClients.add(new TvdotcomClient()); List<SelectButton.Entry<EpisodeListClient>> episodeListClients = new ArrayList<SelectButton.Entry<EpisodeListClient>>();
episodeListClients.add(new AnidbClient());
episodeListClients.add(new TVRageClient());
HashMap<EpisodeListClient, ImageIcon> icons = new HashMap<EpisodeListClient, ImageIcon>(); for (EpisodeListClient client : EpisodeListClient.getAvailableEpisodeListClients()) {
episodeListClients.add(new SelectButton.Entry<EpisodeListClient>(client, client.getIcon()));
for (EpisodeListClient searchEngine : episodeListClients) {
icons.put(searchEngine, searchEngine.getIcon());
} }
searchField = new TextFieldWithSelect<EpisodeListClient>(episodeListClients, icons); searchField = new TextFieldWithSelect<EpisodeListClient>(episodeListClients);
searchField.getSelectButton().addPropertyChangeListener(SelectButton.SELECTED_VALUE_PROPERTY, searchFieldListener); searchField.getSelectButton().addPropertyChangeListener(SelectButton.SELECTED_VALUE_PROPERTY, searchFieldListener);
searchField.getTextField().setColumns(25); searchField.getTextField().setColumns(25);
searchFieldCompletion = new TextCompletion(searchField.getTextField()); searchFieldCompletion = new TextCompletion(searchField.getTextField());
searchFieldCompletion.addCompletionTerms(Settings.getSettings().getTvShowCompletionTerms()); searchFieldCompletion.addCompletionTerms(Settings.getSettings().getStringList(Settings.SEARCH_HISTORY));
searchFieldCompletion.hook(); searchFieldCompletion.hook();
JPanel mainPanel = new JPanel(new BorderLayout(5, 5)); JPanel mainPanel = new JPanel(new BorderLayout(5, 5));
@ -224,27 +213,17 @@ public class SearchPanel extends FileBotPanel {
private class SpinSearchEngineAction extends AbstractAction { private class SpinSearchEngineAction extends AbstractAction {
private int spinOffset; private int spin;
public SpinSearchEngineAction(int spinOffset) { public SpinSearchEngineAction(int spin) {
super("Spin Search Engine"); super("Spin Search Engine");
this.spinOffset = spinOffset; this.spin = spin;
} }
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
EpisodeListClient current = searchField.getSelectedValue(); searchField.getSelectButton().spinValue(spin);
int nextIndex = episodeListClients.indexOf(current) + spinOffset;
int maxIndex = episodeListClients.size() - 1;
if (nextIndex < 0)
nextIndex = maxIndex;
else if (nextIndex > maxIndex)
nextIndex = 0;
searchField.getSelectButton().setSelectedValue(episodeListClients.get(nextIndex));
} }
} }
@ -327,8 +306,9 @@ public class SearchPanel extends FileBotPanel {
} catch (Exception e) { } catch (Exception e) {
tabbedPane.remove(episodeList); tabbedPane.remove(episodeList);
MessageManager.showWarning(FileBotUtil.getRootCause(e).getMessage()); Throwable cause = FileBotUtil.getRootCause(e);
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString()); MessageManager.showWarning(cause.getMessage());
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, cause.toString());
return; return;
} }
@ -356,9 +336,10 @@ public class SearchPanel extends FileBotPanel {
} }
searchFieldCompletion.addCompletionTerm(showname); searchFieldCompletion.addCompletionTerm(showname);
Settings.getSettings().setTvShowCompletionTerms(searchFieldCompletion.getCompletionTerms()); Settings.getSettings().putStringList(Settings.SEARCH_HISTORY, searchFieldCompletion.getCompletionTerms());
String title = showname; String title = showname;
if (task.getNumberOfSeason() != SeasonSpinnerEditor.ALL_SEASONS) if (task.getNumberOfSeason() != SeasonSpinnerEditor.ALL_SEASONS)
title += " - Season " + task.getNumberOfSeason(); title += " - Season " + task.getNumberOfSeason();

View File

@ -134,4 +134,5 @@ public class AnidbClient extends EpisodeListClient {
return new URL("http", host, file); return new URL("http", host, file);
} }
} }

View File

@ -3,6 +3,7 @@ package net.sourceforge.filebot.web;
import java.net.URL; import java.net.URL;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
@ -10,6 +11,30 @@ import javax.swing.ImageIcon;
public abstract class EpisodeListClient { public abstract class EpisodeListClient {
private static LinkedHashSet<EpisodeListClient> registry = new LinkedHashSet<EpisodeListClient>();
static {
registry.add(new TvdotcomClient());
registry.add(new AnidbClient());
registry.add(new TVRageClient());
}
public static Iterable<EpisodeListClient> getAvailableEpisodeListClients() {
return registry;
}
public static EpisodeListClient forName(String name) {
for (EpisodeListClient client : registry) {
if (name.equals(client.getName()))
return client;
}
return null;
}
/** /**
* List of shows * List of shows
*/ */
@ -25,7 +50,7 @@ public abstract class EpisodeListClient {
public abstract List<Episode> getEpisodeList(String showname, int season) throws Exception; public abstract List<Episode> getEpisodeList(String showname, int season) throws Exception;
public abstract URL getEpisodeListUrl(String showname, int season) throws Exception; public abstract URL getEpisodeListUrl(String showname, int season);
public boolean isSingleSeasonSupported() { public boolean isSingleSeasonSupported() {

View File

@ -88,7 +88,7 @@ public class TVRageClient extends EpisodeListClient {
Matcher seasonMatcher = Pattern.compile("Season (\\d+)").matcher(seasonHeader); Matcher seasonMatcher = Pattern.compile("Season (\\d+)").matcher(seasonHeader);
if (seasonMatcher.matches()) { if (seasonMatcher.matches()) {
if (season == 0 || season == Integer.parseInt(seasonMatcher.group(1))) { if ((season == 0) || (season == Integer.parseInt(seasonMatcher.group(1)))) {
Matcher saeMatcher = Pattern.compile("(\\d+)x(\\d+)").matcher(seasonAndEpisodeNumber); Matcher saeMatcher = Pattern.compile("(\\d+)x(\\d+)").matcher(seasonAndEpisodeNumber);
String seasonNumber = null; String seasonNumber = null;
@ -133,4 +133,5 @@ public class TVRageClient extends EpisodeListClient {
String file = "/search.php?search=" + qs; String file = "/search.php?search=" + qs;
return new URL("http", host, file); return new URL("http", host, file);
} }
} }

View File

@ -139,4 +139,5 @@ public class TvdotcomClient extends EpisodeListClient {
return new URL("http", host, file); return new URL("http", host, file);
} }
} }

View File

@ -24,8 +24,6 @@ public class FancyListCellRenderer extends DefaultListCellRenderer {
private Color gradientEndColor; private Color gradientEndColor;
private boolean highlightingEnabled;
private Border defaultBorder; private Border defaultBorder;
private Border selectedBorder; private Border selectedBorder;
@ -36,9 +34,11 @@ public class FancyListCellRenderer extends DefaultListCellRenderer {
private Insets padding; private Insets padding;
private boolean highlightingEnabled;
public FancyListCellRenderer() { public FancyListCellRenderer() {
this(GradientStyle.TOP_TO_BOTTOM, false, new Insets(7, 7, 7, 7), new Insets(1, 1, 0, 1), null); this(GradientStyle.TOP_TO_BOTTOM, true, new Insets(7, 7, 7, 7), new Insets(1, 1, 0, 1), null);
} }

View File

@ -15,8 +15,9 @@ import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.geom.GeneralPath; import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D; import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.JButton; import javax.swing.JButton;
@ -35,17 +36,18 @@ public class SelectButton<T> extends JButton implements ActionListener {
private Color beginColorHover = beginColor; private Color beginColorHover = beginColor;
private Color endColorHover = Color.decode("#D8D7CD"); private Color endColorHover = Color.decode("#D8D7CD");
private T selectedValue = null; private Entry<T> selectedEntry = null;
private List<T> options; private List<Entry<T>> entries = new ArrayList<Entry<T>>();
private Map<T, ? extends Icon> icons;
public static final String SELECTED_VALUE_PROPERTY = "SELECTED_VALUE_PROPERTY"; public static final String SELECTED_VALUE_PROPERTY = "SELECTED_VALUE_PROPERTY";
public SelectButton(List<T> options, Map<T, ? extends Icon> icons) { public SelectButton(Collection<Entry<T>> entries) {
this.options = options; if (entries.isEmpty())
this.icons = icons; throw new IllegalArgumentException("Entries must not be empty");
this.entries.addAll(entries);
setContentAreaFilled(false); setContentAreaFilled(false);
setFocusable(false); setFocusable(false);
@ -57,36 +59,70 @@ public class SelectButton<T> extends JButton implements ActionListener {
addMouseListener(new MouseInputListener()); addMouseListener(new MouseInputListener());
// select first option
setSelectedValue(options.iterator().next());
setPreferredSize(new Dimension(32, 22)); setPreferredSize(new Dimension(32, 22));
// select first entry
setSelectedIndex(0);
} }
public void setSelectedValue(T value) { public void setSelectedValue(T value) {
if (selectedValue == value) Entry<T> entry = find(value);
if (entry == null)
return; return;
T oldSelectedValue = selectedValue; selectedEntry = entry;
setIcon(new SelectIcon(selectedEntry.getIcon()));
selectedValue = value; firePropertyChange(SELECTED_VALUE_PROPERTY, null, selectedEntry);
Icon icon = icons.get(selectedValue);
setIcon(new SelectIcon(icon));
firePropertyChange(SELECTED_VALUE_PROPERTY, oldSelectedValue, selectedValue);
} }
public T getSelectedValue() { public T getSelectedEntry() {
return selectedValue; return selectedEntry.getValue();
}
public void setSelectedIndex(int i) {
setSelectedValue(entries.get(i).getValue());
}
public int getSelectedIndex() {
return entries.indexOf(selectedEntry);
}
private Entry<T> find(T value) {
for (Entry<T> entry : entries) {
if (entry.value == value)
return entry;
}
return null;
}
public void spinValue(int spin) {
spin = spin % entries.size();
int next = getSelectedIndex() + spin;
if (next < 0)
next += entries.size();
else if (next >= entries.size())
next -= entries.size();
setSelectedIndex(next);
} }
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
JPopupMenu popup = new JPopupMenu(); JPopupMenu popup = new JPopupMenu();
for (T option : options) { for (Entry<T> entry : entries) {
popup.add(new SelectMenuIem(option)); popup.add(new SelectMenuItem(entry));
} }
popup.show(this, 0, getHeight() - 1); popup.show(this, 0, getHeight() - 1);
@ -108,22 +144,24 @@ public class SelectButton<T> extends JButton implements ActionListener {
} }
private class SelectMenuIem extends JMenuItem implements ActionListener { private class SelectMenuItem extends JMenuItem implements ActionListener {
private T value; private T value;
public SelectMenuIem(T value) { public SelectMenuItem(Entry<T> entry) {
super(value.toString(), icons.get(value)); super(entry.toString(), entry.getIcon());
this.value = value; this.value = entry.getValue();
this.setMargin(new Insets(3, 0, 3, 0)); this.setMargin(new Insets(3, 0, 3, 0));
this.addActionListener(this); this.addActionListener(this);
if (this.value == getSelectedValue()) if (this.value == getSelectedEntry())
this.setFont(this.getFont().deriveFont(Font.BOLD)); this.setFont(this.getFont().deriveFont(Font.BOLD));
} }
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
setSelectedValue(value); setSelectedValue(value);
} }
@ -189,4 +227,33 @@ public class SelectButton<T> extends JButton implements ActionListener {
} }
public static class Entry<T> {
private T value;
private Icon icon;
public Entry(T value, Icon icon) {
this.value = value;
this.icon = icon;
}
public T getValue() {
return value;
}
public Icon getIcon() {
return icon;
}
@Override
public String toString() {
return value.toString();
}
}
} }

View File

@ -6,15 +6,15 @@ import java.awt.BorderLayout;
import java.awt.Color; import java.awt.Color;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.List; import java.util.Collection;
import java.util.Map;
import javax.swing.BorderFactory; import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.border.Border; import javax.swing.border.Border;
import net.sourceforge.tuned.ui.SelectButton.Entry;
public class TextFieldWithSelect<T> extends JPanel { public class TextFieldWithSelect<T> extends JPanel {
@ -24,10 +24,10 @@ public class TextFieldWithSelect<T> extends JPanel {
private Color borderColor = Color.decode("#A4A4A4"); private Color borderColor = Color.decode("#A4A4A4");
public TextFieldWithSelect(List<T> options, Map<T, ? extends Icon> icons) { public TextFieldWithSelect(Collection<Entry<T>> options) {
setLayout(new BorderLayout(0, 0)); setLayout(new BorderLayout(0, 0));
selectButton = new SelectButton<T>(options, icons); selectButton = new SelectButton<T>(options);
selectButton.addActionListener(textFieldFocusOnClick); selectButton.addActionListener(textFieldFocusOnClick);
Border lineBorder = BorderFactory.createLineBorder(borderColor, 1); Border lineBorder = BorderFactory.createLineBorder(borderColor, 1);
@ -54,7 +54,7 @@ public class TextFieldWithSelect<T> extends JPanel {
public T getSelectedValue() { public T getSelectedValue() {
return selectButton.getSelectedValue(); return selectButton.getSelectedEntry();
} }