mirror of
https://github.com/mitb-archive/filebot
synced 2025-03-09 13:59:49 -04:00
Refactor Presets and enable keyboard shortcuts for Presets 1..9 via number keys
This commit is contained in:
parent
dcfcc91090
commit
824ce14c62
@ -16,6 +16,7 @@ import net.filebot.archive.Archive.Extractor;
|
||||
import net.filebot.cli.ArgumentBean;
|
||||
import net.filebot.util.PreferencesList;
|
||||
import net.filebot.util.PreferencesMap;
|
||||
import net.filebot.util.PreferencesMap.JsonAdapter;
|
||||
import net.filebot.util.PreferencesMap.PreferencesEntry;
|
||||
import net.filebot.util.PreferencesMap.StringAdapter;
|
||||
|
||||
@ -234,10 +235,18 @@ public final class Settings {
|
||||
return PreferencesMap.map(prefs);
|
||||
}
|
||||
|
||||
public <T> PreferencesMap<T> asTypedMap(Class<T> cls) {
|
||||
return PreferencesMap.map(prefs, new JsonAdapter(cls));
|
||||
}
|
||||
|
||||
public PreferencesList<String> asList() {
|
||||
return PreferencesList.map(prefs);
|
||||
}
|
||||
|
||||
public <T> PreferencesList<T> asTypedList(Class<T> cls) {
|
||||
return PreferencesList.map(prefs, new JsonAdapter(cls));
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
try {
|
||||
// remove child nodes
|
||||
|
@ -41,12 +41,11 @@ import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.TitledBorder;
|
||||
|
||||
import com.cedarsoftware.util.io.JsonReader;
|
||||
import com.cedarsoftware.util.io.JsonWriter;
|
||||
import com.google.common.eventbus.Subscribe;
|
||||
|
||||
import ca.odell.glazedlists.EventList;
|
||||
@ -110,6 +109,8 @@ public class RenamePanel extends JComponent {
|
||||
private static final PreferencesEntry<String> persistentPreferredLanguage = Settings.forPackage(RenamePanel.class).entry("rename.language").defaultValue("en");
|
||||
private static final PreferencesEntry<String> persistentPreferredEpisodeOrder = Settings.forPackage(RenamePanel.class).entry("rename.episode.order").defaultValue("Airdate");
|
||||
|
||||
private static final Map<String, Preset> persistentPresets = Settings.forPackage(RenamePanel.class).node("presets").asTypedMap(Preset.class);
|
||||
|
||||
public RenamePanel() {
|
||||
namesList.setTitle("New Names");
|
||||
namesList.setTransferablePolicy(new NamesListTransferablePolicy(renameModel.values()));
|
||||
@ -241,9 +242,8 @@ public class RenamePanel extends JComponent {
|
||||
filesList.getButtonPanel().add(createImageButton(openHistoryAction), "gap indent");
|
||||
|
||||
// create macros popup
|
||||
final Action macrosAction = new ShowPresetsPopupAction("Presets", ResourceManager.getIcon("action.script"));
|
||||
JButton macrosButton = createImageButton(macrosAction);
|
||||
filesList.getButtonPanel().add(macrosButton, "gap 0");
|
||||
JButton presetsButton = createImageButton(new ShowPresetsPopupAction("Presets", ResourceManager.getIcon("action.script")));
|
||||
filesList.getButtonPanel().add(presetsButton, "gap 0");
|
||||
|
||||
// show popup on actionPerformed only when names list is empty
|
||||
matchButton.addActionListener(evt -> {
|
||||
@ -302,8 +302,13 @@ public class RenamePanel extends JComponent {
|
||||
|
||||
add(new LoadingOverlayPane(namesList, namesList, "37px", "30px"), "grow, sizegroupx list");
|
||||
|
||||
// install F2 and 1..9 keystroke actions
|
||||
SwingUtilities.invokeLater(this::installKeyStrokeActions);
|
||||
}
|
||||
|
||||
private void installKeyStrokeActions() {
|
||||
// manual force name via F2
|
||||
installAction(namesList.getListComponent(), getKeyStroke(VK_F2, 0), newAction("Force Name", evt -> {
|
||||
installAction(this, WHEN_IN_FOCUSED_WINDOW, getKeyStroke(VK_F2, 0), newAction("Force Name", evt -> {
|
||||
try {
|
||||
if (namesList.getModel().isEmpty()) {
|
||||
withWaitCursor(evt.getSource(), () -> {
|
||||
@ -336,61 +341,72 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.WARNING, e.getMessage(), e);
|
||||
debug.log(Level.WARNING, e::toString);
|
||||
}
|
||||
}));
|
||||
|
||||
// map 1..9 number keys to presets
|
||||
try {
|
||||
Preset[] presets = persistentPresets.values().toArray(new Preset[0]);
|
||||
|
||||
for (int i = 0; i < presets.length && i < 9; i++) {
|
||||
Preset preset = presets[i];
|
||||
int key = Character.forDigit(i + 1, 10);
|
||||
|
||||
installAction(this, WHEN_IN_FOCUSED_WINDOW, getKeyStroke(key, 0), newAction(preset.getName(), new ApplyPresetAction(preset)::actionPerformed));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.WARNING, e::toString);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMatchModeStrict() {
|
||||
return MATCH_MODE_STRICT.equalsIgnoreCase(persistentPreferredMatchMode.getValue());
|
||||
}
|
||||
|
||||
protected ActionPopup createPresetsPopup() {
|
||||
Map<String, String> persistentPresets = Settings.forPackage(RenamePanel.class).node("presets").asMap();
|
||||
private ActionPopup createPresetsPopup() {
|
||||
ActionPopup actionPopup = new ActionPopup("Presets", ResourceManager.getIcon("action.script"));
|
||||
|
||||
if (persistentPresets.size() > 0) {
|
||||
for (String it : persistentPresets.values()) {
|
||||
try {
|
||||
Preset p = (Preset) JsonReader.jsonToJava(it);
|
||||
actionPopup.add(new ApplyPresetAction(p));
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.SEVERE, e.getMessage(), e);
|
||||
try {
|
||||
if (persistentPresets.size() > 0) {
|
||||
for (Preset preset : persistentPresets.values()) {
|
||||
actionPopup.add(new ApplyPresetAction(preset));
|
||||
}
|
||||
actionPopup.addSeparator();
|
||||
}
|
||||
actionPopup.addSeparator();
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.WARNING, e, e::toString);
|
||||
}
|
||||
|
||||
actionPopup.add(newAction("Edit Presets", ResourceManager.getIcon("script.add"), evt -> {
|
||||
try {
|
||||
String newPresetOption = "New Preset …";
|
||||
String newPreset = "New Preset …";
|
||||
List<String> presetNames = new ArrayList<String>(persistentPresets.keySet());
|
||||
presetNames.add(newPresetOption);
|
||||
presetNames.add(newPreset);
|
||||
|
||||
String selection = (String) showInputDialog(getWindow(evt.getSource()), "Edit or create a preset:", "Edit Preset", PLAIN_MESSAGE, null, presetNames.toArray(), newPresetOption);
|
||||
if (selection == null)
|
||||
String selection = (String) showInputDialog(getWindow(evt.getSource()), "Edit or create a preset:", "Edit Preset", PLAIN_MESSAGE, null, presetNames.toArray(), newPreset);
|
||||
if (selection == null) {
|
||||
return;
|
||||
|
||||
Preset preset = null;
|
||||
if (selection == newPresetOption) {
|
||||
selection = (String) showInputDialog(getWindow(evt.getSource()), "Preset Name:", newPresetOption, PLAIN_MESSAGE, null, null, "My Preset");
|
||||
if (selection == null || selection.trim().isEmpty())
|
||||
return;
|
||||
|
||||
preset = new Preset(selection.trim(), null, null, null, null, null, null, null, null);
|
||||
} else {
|
||||
preset = (Preset) JsonReader.jsonToJava(persistentPresets.get(selection.toString()));
|
||||
}
|
||||
|
||||
PresetEditor presetEditor = new PresetEditor(getWindow(evt.getSource()));
|
||||
|
||||
if (selection == newPreset) {
|
||||
selection = (String) showInputDialog(getWindow(evt.getSource()), "Preset Name:", newPreset, PLAIN_MESSAGE, null, null, "My Preset");
|
||||
if (selection == null || selection.trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
presetEditor.setPreset(new Preset(selection.trim(), null, null, null, null, null, null, null, null));
|
||||
} else {
|
||||
presetEditor.setPreset(persistentPresets.get(selection));
|
||||
}
|
||||
|
||||
presetEditor.setLocation(getOffsetLocation(presetEditor.getOwner()));
|
||||
presetEditor.setPreset(preset);
|
||||
presetEditor.setVisible(true);
|
||||
|
||||
switch (presetEditor.getResult()) {
|
||||
case SET:
|
||||
preset = presetEditor.getPreset();
|
||||
persistentPresets.put(selection, JsonWriter.objectToJson(preset));
|
||||
persistentPresets.put(selection, presetEditor.getPreset());
|
||||
break;
|
||||
case DELETE:
|
||||
persistentPresets.remove(selection);
|
||||
@ -399,14 +415,14 @@ public class RenamePanel extends JComponent {
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.WARNING, e.toString());
|
||||
debug.log(Level.WARNING, e, e::toString);
|
||||
}
|
||||
}));
|
||||
|
||||
return actionPopup;
|
||||
}
|
||||
|
||||
protected ActionPopup createFetchPopup() {
|
||||
private ActionPopup createFetchPopup() {
|
||||
ActionPopup actionPopup = new ActionPopup("Fetch & Match Data", ResourceManager.getIcon("action.fetch"));
|
||||
|
||||
actionPopup.addDescription(new JLabel("Episode Mode:"));
|
||||
@ -508,7 +524,7 @@ public class RenamePanel extends JComponent {
|
||||
return actionPopup;
|
||||
}
|
||||
|
||||
protected ActionPopup createSettingsPopup() {
|
||||
private ActionPopup createSettingsPopup() {
|
||||
ActionPopup actionPopup = new ActionPopup("Rename Options", ResourceManager.getIcon("action.settings"));
|
||||
|
||||
actionPopup.addDescription(new JLabel("Extension:"));
|
||||
@ -525,7 +541,7 @@ public class RenamePanel extends JComponent {
|
||||
return actionPopup;
|
||||
}
|
||||
|
||||
protected Mode getFormatEditorMode(MediaBindingBean binding) {
|
||||
private Mode getFormatEditorMode(MediaBindingBean binding) {
|
||||
if (binding != null) {
|
||||
if (binding.getInfoObject() instanceof Episode) {
|
||||
return Mode.Episode;
|
||||
@ -549,7 +565,7 @@ public class RenamePanel extends JComponent {
|
||||
return Mode.Episode; // default to Episode mode
|
||||
}
|
||||
|
||||
protected void showFormatEditor(MediaBindingBean binding) {
|
||||
private void showFormatEditor(MediaBindingBean binding) {
|
||||
try {
|
||||
withWaitCursor(this, () -> {
|
||||
FormatDialog dialog = new FormatDialog(getWindowAncestor(RenamePanel.this), getFormatEditorMode(binding), binding);
|
||||
@ -586,7 +602,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected final Action clearFilesAction = newAction("Clear All", ResourceManager.getIcon("action.clear"), evt -> {
|
||||
private final Action clearFilesAction = newAction("Clear All", ResourceManager.getIcon("action.clear"), evt -> {
|
||||
if (isShiftOrAltDown(evt)) {
|
||||
renameModel.files().clear();
|
||||
} else {
|
||||
@ -594,7 +610,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
});
|
||||
|
||||
protected final Action openHistoryAction = newAction("Open History", ResourceManager.getIcon("action.report"), evt -> {
|
||||
private final Action openHistoryAction = newAction("Open History", ResourceManager.getIcon("action.report"), evt -> {
|
||||
try {
|
||||
History model = HistorySpooler.getInstance().getCompleteHistory();
|
||||
|
||||
@ -619,7 +635,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected static class ShowPopupAction extends AbstractAction {
|
||||
private static class ShowPopupAction extends AbstractAction {
|
||||
|
||||
public ShowPopupAction(String name, Icon icon) {
|
||||
super(name, icon);
|
||||
@ -633,7 +649,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
};
|
||||
|
||||
protected class ShowPresetsPopupAction extends AbstractAction {
|
||||
private class ShowPresetsPopupAction extends AbstractAction {
|
||||
|
||||
public ShowPresetsPopupAction(String name, Icon icon) {
|
||||
super(name, icon);
|
||||
@ -647,7 +663,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
};
|
||||
|
||||
protected class ApplyPresetAction extends AutoCompleteAction {
|
||||
private class ApplyPresetAction extends AutoCompleteAction {
|
||||
|
||||
private Preset preset;
|
||||
|
||||
@ -724,7 +740,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected class SetRenameMode extends AbstractAction {
|
||||
private class SetRenameMode extends AbstractAction {
|
||||
|
||||
private final boolean activate;
|
||||
|
||||
@ -745,7 +761,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected class SetRenameAction extends AbstractAction {
|
||||
private class SetRenameAction extends AbstractAction {
|
||||
|
||||
private final StandardRenameAction action;
|
||||
|
||||
@ -766,7 +782,7 @@ public class RenamePanel extends JComponent {
|
||||
}
|
||||
}
|
||||
|
||||
protected class AutoCompleteAction extends AbstractAction {
|
||||
private class AutoCompleteAction extends AbstractAction {
|
||||
|
||||
protected final Supplier<AutoCompleteMatcher> matcher;
|
||||
|
||||
|
@ -2,12 +2,6 @@ package net.filebot.util;
|
||||
|
||||
import static net.filebot.Logging.*;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -20,6 +14,9 @@ import java.util.logging.Level;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
import com.cedarsoftware.util.io.JsonReader;
|
||||
import com.cedarsoftware.util.io.JsonWriter;
|
||||
|
||||
public class PreferencesMap<T> implements Map<String, T> {
|
||||
|
||||
private final Preferences prefs;
|
||||
@ -220,40 +217,32 @@ public class PreferencesMap<T> implements Map<String, T> {
|
||||
|
||||
}
|
||||
|
||||
public static class SerializableAdapter<T extends Serializable> extends AbstractAdapter<T> {
|
||||
public static class JsonAdapter<T> extends AbstractAdapter<T> {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
public JsonAdapter(Class<T> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T get(Preferences prefs, String key) {
|
||||
byte[] bytes = prefs.getByteArray(key, null);
|
||||
String json = prefs.get(key, null);
|
||||
|
||||
if (bytes == null)
|
||||
return null;
|
||||
|
||||
try {
|
||||
ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bytes));
|
||||
Object object = in.readObject();
|
||||
in.close();
|
||||
|
||||
return (T) object;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
if (json != null) {
|
||||
try {
|
||||
return type.cast(JsonReader.jsonToJava(json));
|
||||
} catch (Exception e) {
|
||||
debug.log(Level.WARNING, e, e::getMessage);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(Preferences prefs, String key, T value) {
|
||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
|
||||
try {
|
||||
ObjectOutputStream out = new ObjectOutputStream(buffer);
|
||||
out.writeObject(value);
|
||||
out.close();
|
||||
|
||||
prefs.putByteArray(key, buffer.toByteArray());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
prefs.put(key, JsonWriter.objectToJson(value));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,20 +139,24 @@ public final class SwingUI {
|
||||
}
|
||||
|
||||
public static void installAction(JComponent component, KeyStroke keystroke, Action action) {
|
||||
installAction(component, JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, keystroke, action);
|
||||
}
|
||||
|
||||
public static void installAction(JComponent component, int condition, KeyStroke keystroke, Action action) {
|
||||
Object key = action.getValue(Action.NAME);
|
||||
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Action must have a name");
|
||||
}
|
||||
|
||||
component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(keystroke, key);
|
||||
component.getInputMap(condition).put(keystroke, key);
|
||||
component.getActionMap().put(key, action);
|
||||
|
||||
// automatically add Mac OS X compatibility (on Mac the BACKSPACE key is called DELETE, and there is no DELETE key)
|
||||
if (keystroke.getKeyCode() == KeyEvent.VK_DELETE) {
|
||||
KeyStroke macKeyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_BACK_SPACE, keystroke.getModifiers(), keystroke.isOnKeyRelease());
|
||||
Object macKey = "mac." + action.getValue(Action.NAME);
|
||||
component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(macKeyStroke, macKey);
|
||||
component.getInputMap(condition).put(macKeyStroke, macKey);
|
||||
component.getActionMap().put(macKey, action);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import net.filebot.util.PreferencesMap.SerializableAdapter;
|
||||
import net.filebot.util.PreferencesMap.JsonAdapter;
|
||||
import net.filebot.util.PreferencesMap.SimpleAdapter;
|
||||
|
||||
public class PreferencesMapTest {
|
||||
@ -144,11 +144,12 @@ public class PreferencesMapTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializableAdapter() {
|
||||
Map<String, Color> map = PreferencesMap.map(temp, new SerializableAdapter<Color>());
|
||||
public void jsonAdapter() {
|
||||
Map<String, Color> map = PreferencesMap.map(temp, new JsonAdapter<Color>(Color.class));
|
||||
Color color = new Color(0.25f, 0.50f, 1.00f);
|
||||
|
||||
map.put("color", color);
|
||||
assertEquals(color, map.get("color"));
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user