Lots of refactoring:

* Removed TransferablePolicySupport and related refactoring
* OpenSubtitlesClient: ignore logout status code
* Animated-GIF are animated again
* Unrar process will not hang anymore
* Improved Subscene scraper
* Better scaling for ProgressIndicator
* Added \r and \n to invalid characters
* Some work on SubtitlePanel and related stuff
* Setting putMap/List methods clear existing data first
This commit is contained in:
Reinhard Pointner 2008-06-02 19:12:28 +00:00
parent 12d453eff4
commit 30a54c2cf4
64 changed files with 742 additions and 599 deletions

View File

@ -15,10 +15,16 @@
<property name="lib.nekohtml" value="nekohtml-1.9.7.jar" />
<property name="lib.simmetrics" value="simmetrics_jar_v1_6_2_d07_02_07.jar" />
<property name="lib.xmlrpc" value="xmlrpc-client-1.1.jar" />
<patternset id="classes">
<include name="**/*.class" />
<include name="**/*.properties" />
<exclude name="**/*Test*" />
</patternset>
<target name="jar" depends="build">
<target name="fatjar" depends="build">
<jar destfile="${executable}" duplicate="fail">
<fileset dir="${build}" />
@ -28,38 +34,27 @@
<attribute name="Version" value="${version}" />
</manifest>
<!-- include libs if fatjar is set -->
<zipfileset src="${lib}/${lib.xerces}">
<include if="fatjar" name="**/*.class" />
<include if="fatjar" name="**/*.properties" />
<exclude if="fatjar" name="**/*Test*" />
<patternset refid="classes" />
</zipfileset>
<zipfileset src="${lib}/${lib.nekohtml}">
<include if="fatjar" name="**/*.class" />
<include if="fatjar" name="**/*.properties" />
<exclude if="fatjar" name="**/*Test*" />
<patternset refid="classes" />
</zipfileset>
<zipfileset src="${lib}/${lib.simmetrics}">
<include if="fatjar" name="**/*.class" />
<include if="fatjar" name="**/*.properties" />
<exclude if="fatjar" name="**/*Test*" />
<patternset refid="classes" />
</zipfileset>
<zipfileset src="${lib}/${lib.xmlrpc}">
<include if="fatjar" name="**/*.class" />
<include if="fatjar" name="**/*.properties" />
<exclude if="fatjar" name="**/*Test*" />
<patternset refid="classes" />
</zipfileset>
</jar>
</target>
<target name="fatjar">
<antcall target="jar">
<param name="fatjar" value="true" />
</antcall>
</target>
<target name="build" depends="clean">
<!-- create build dir -->
<mkdir dir="${build}" />

View File

@ -4,7 +4,11 @@ package net.sourceforge.filebot;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.List;
import java.util.regex.Pattern;
@ -16,9 +20,9 @@ public class FileBotUtil {
}
/**
* invalid characters: \, /, :, *, ?, ", <, > and |
* invalid characters: \, /, :, *, ?, ", <, >, |, \r and \n
*/
public static final String INVALID_CHARACTERS = "\\/:*?\"<>|";
public static final String INVALID_CHARACTERS = "\\/:*?\"<>|\r\n";
public static final Pattern INVALID_CHARACTERS_PATTERN = Pattern.compile(String.format("[%s]+", Pattern.quote(INVALID_CHARACTERS)));
@ -114,4 +118,12 @@ public class FileBotUtil {
};
//TODO needed??
public static void writeToFile(File file, ByteBuffer data) throws IOException {
FileChannel channel = new FileOutputStream(file).getChannel();
channel.write(data);
channel.close();
}
}

View File

@ -26,14 +26,14 @@ public class Settings {
public static final String SUBTITLE_HISTORY = "subtitle/history";
public static final String SUBTITLE_LANGUAGE = "subtitle/language";
private static Settings settings = new Settings();
private static final Settings settings = new Settings();
public static Settings getSettings() {
return settings;
}
private Preferences prefs;
private final Preferences prefs;
private Settings() {
@ -89,7 +89,7 @@ public class Settings {
public void putStringList(String key, Collection<String> list) {
Preferences listNode = prefs.node(key);
Preferences listNode = getClearNode(key);
int i = 0;
@ -118,7 +118,7 @@ public class Settings {
public void putStringMap(String key, Map<String, String> map) {
Preferences mapNode = prefs.node(key);
Preferences mapNode = getClearNode(key);
for (Map.Entry<String, String> entry : map.entrySet()) {
mapNode.put(entry.getKey(), entry.getValue());
@ -185,10 +185,24 @@ public class Settings {
public void clear() {
try {
prefs.removeNode();
prefs = Preferences.userRoot().node(ROOT);
for (String child : prefs.childrenNames()) {
prefs.node(child).removeNode();
}
} catch (BackingStoreException e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
}
private Preferences getClearNode(String nodeName) {
Preferences node = prefs.node(nodeName);
try {
node.clear();
} catch (BackingStoreException e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
return node;
}
}

View File

@ -9,8 +9,6 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
@ -30,59 +28,47 @@ public class ResourceManager {
aliasMap.put("loading", "loading.gif");
}
private static final Map<String, Image> cache = Collections.synchronizedMap(new WeakHashMap<String, Image>());
private static final Map<String, ImageIcon> iconCache = Collections.synchronizedMap(new WeakHashMap<String, ImageIcon>());
public static ImageIcon getIcon(String name) {
return new ImageIcon(getImage(name));
return getIcon(name, null);
}
public static ImageIcon getIcon(String name, String def) {
ImageIcon icon = iconCache.get(name);
if (icon == null) {
// load image if not in cache
URL resource = getResource(name, def);
if (resource != null) {
icon = new ImageIcon(resource);
iconCache.put(name, icon);
}
}
return icon;
}
public static ImageIcon getFlagIcon(String languageCode) {
if (languageCode == null)
languageCode = "default";
return new ImageIcon(getImage(String.format("flags/%s", languageCode.toLowerCase()), "flags/default"));
return getIcon(String.format("flags/%s", languageCode), "flags/default");
}
public static ImageIcon getArchiveIcon(String type) {
if (type == null)
type = "default";
return new ImageIcon(getImage(String.format("archives/%s", type.toLowerCase()), "archives/default"));
return getIcon(String.format("archives/%s", type), "archives/default");
}
public static Image getImage(String name) {
Image image = cache.get(name);
if (image == null) {
try {
// load image if not in cache
URL resource = getResource(name);
if (resource != null) {
image = ImageIO.read(resource);
cache.put(name, image);
}
} catch (IOException e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}
try {
return ImageIO.read(getResource(name));
} catch (IOException e) {
throw new RuntimeException(e);
}
return image;
}
private static Image getImage(String name, String def) {
Image image = getImage(name);
// image not found, use default
if (image == null)
image = getImage(def);
return image;
}
@ -97,4 +83,14 @@ public class ResourceManager {
return ResourceManager.class.getResource(resource);
}
private static URL getResource(String name, String def) {
URL resource = getResource(name);
if (resource == null)
resource = getResource(def);
return resource;
}
}

View File

@ -22,35 +22,28 @@ import javax.swing.border.TitledBorder;
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
import net.sourceforge.filebot.ui.transfer.ExportHandler;
import net.sourceforge.filebot.ui.transfer.FileTransferable;
import net.sourceforge.filebot.ui.transfer.ImportHandler;
import net.sourceforge.filebot.ui.transfer.Saveable;
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
import net.sourceforge.filebot.ui.transferablepolicies.MutableTransferablePolicy;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
import net.sourceforge.tuned.ui.DefaultFancyListCellRenderer;
import net.sourceforge.tuned.ui.SimpleListModel;
import net.sourceforge.tuned.ui.TunedUtil;
public class FileBotList extends JPanel implements Saveable, TransferablePolicySupport {
public class FileBotList extends JPanel implements Saveable {
private JList list = new JList(new SimpleListModel());
private final JList list = new JList(new SimpleListModel());
private TitledBorder titledBorder;
private final MutableTransferablePolicy mutableTransferablePolicy = new MutableTransferablePolicy();
private final TitledBorder titledBorder;
private String title;
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
public FileBotList(boolean enableDrop, boolean enableDrag, boolean enableRemoveAction) {
this(enableDrop, enableDrag, enableRemoveAction, true);
}
public FileBotList(boolean enableImport, boolean enableExport, boolean enableRemoveAction, boolean border) {
public FileBotList(boolean enableExport, boolean enableRemoveAction, boolean border) {
super(new BorderLayout());
JScrollPane listScrollPane = new JScrollPane(list);
@ -59,6 +52,7 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
titledBorder = new TitledBorder("");
setBorder(titledBorder);
} else {
titledBorder = null;
listScrollPane.setBorder(BorderFactory.createEmptyBorder());
}
@ -67,16 +61,12 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
add(listScrollPane, BorderLayout.CENTER);
ImportHandler importHander = null;
ExportHandler exportHandler = null;
if (enableImport)
importHander = new TransferablePolicyImportHandler(this);
if (enableExport)
exportHandler = new SaveableExportHandler(this);
list.setTransferHandler(new DefaultTransferHandler(importHander, exportHandler));
list.setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(mutableTransferablePolicy), exportHandler));
list.setDragEnabled(enableExport);
if (enableRemoveAction) {
@ -92,12 +82,12 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
mutableTransferablePolicy.setTransferablePolicy(transferablePolicy);
}
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
return mutableTransferablePolicy;
}
@ -112,10 +102,8 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
if (titledBorder != null)
titledBorder.setTitle(title);
if (isVisible()) {
revalidate();
repaint();
}
revalidate();
repaint();
}
@ -153,8 +141,8 @@ public class FileBotList extends JPanel implements Saveable, TransferablePolicyS
public void load(List<File> files) {
FileTransferable tr = new FileTransferable(files);
if (transferablePolicy.accept(tr))
transferablePolicy.handleTransferable(tr, false);
if (mutableTransferablePolicy.accept(tr))
mutableTransferablePolicy.handleTransferable(tr, false);
}
private final AbstractAction removeAction = new AbstractAction("Remove") {

View File

@ -20,19 +20,21 @@ import net.sourceforge.filebot.ui.panel.subtitle.SubtitlePanel;
public class FileBotPanel extends JPanel {
private static final List<FileBotPanel> registry = new ArrayList<FileBotPanel>();
static {
registry.add(new ListPanel());
registry.add(new RenamePanel());
registry.add(new AnalyzePanel());
registry.add(new SearchPanel());
registry.add(new SubtitlePanel());
registry.add(new SfvPanel());
}
private static List<FileBotPanel> registry;
public static List<FileBotPanel> getAvailablePanels() {
public static synchronized List<FileBotPanel> getAvailablePanels() {
if (registry == null) {
registry = new ArrayList<FileBotPanel>(6);
registry.add(new ListPanel());
registry.add(new RenamePanel());
registry.add(new AnalyzePanel());
registry.add(new SearchPanel());
registry.add(new SubtitlePanel());
registry.add(new SfvPanel());
}
return Collections.unmodifiableList(registry);
}

View File

@ -33,15 +33,10 @@ class FileBotPanelSelectionList extends JList {
setBorder(new EmptyBorder(4, 5, 4, 5));
// initialize "drag over" panel selection
new DropTarget(this, new DragDropListener());
SimpleListModel model = new SimpleListModel();
for (FileBotPanel panel : FileBotPanel.getAvailablePanels()) {
model.add(panel);
}
setModel(model);
setModel(new SimpleListModel(FileBotPanel.getAvailablePanels()));
}
@ -110,6 +105,7 @@ class FileBotPanelSelectionList extends JList {
}
@Override
public void drop(DropTargetDropEvent dtde) {
}

View File

@ -4,42 +4,30 @@ package net.sourceforge.filebot.ui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import net.sourceforge.filebot.resources.ResourceManager;
public class FileBotTabComponent extends JPanel {
private final JLabel label;
private final JLabel label = new JLabel();
private final JButton closeButton = createCloseButton();
public FileBotTabComponent() {
this("", null);
}
public FileBotTabComponent(String title, Icon icon) {
super(new BorderLayout(0, 0));
setOpaque(false);
label = new JLabel(title, SwingConstants.LEFT);
label.setIcon(icon);
label.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
add(label, BorderLayout.CENTER);
add(new CloseButton(tabCloseAction), BorderLayout.EAST);
add(closeButton, BorderLayout.EAST);
}
@ -58,34 +46,25 @@ public class FileBotTabComponent extends JPanel {
}
public void close() {
JTabbedPane tabs = (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, FileBotTabComponent.this);
tabs.removeTabAt(tabs.indexOfTabComponent(FileBotTabComponent.this));
public JButton getCloseButton() {
return closeButton;
}
private final AbstractAction tabCloseAction = new AbstractAction(null, null) {
private JButton createCloseButton() {
JButton button = new JButton();
public void actionPerformed(ActionEvent e) {
close();
}
};
private class CloseButton extends JButton {
button.setContentAreaFilled(false);
button.setBorderPainted(false);
button.setFocusable(false);
button.setRolloverEnabled(true);
public CloseButton(AbstractAction action) {
super(action);
setContentAreaFilled(false);
setBorderPainted(false);
setFocusable(false);
setIcon(ResourceManager.getIcon("tab.close"));
setRolloverIcon(ResourceManager.getIcon("tab.close.hover"));
setRolloverEnabled(true);
setPreferredSize(new Dimension(17, 17));
}
};
button.setIcon(ResourceManager.getIcon("tab.close"));
button.setRolloverIcon(ResourceManager.getIcon("tab.close.hover"));
button.setPreferredSize(new Dimension(17, 17));
return button;
}
}

View File

@ -26,15 +26,9 @@ import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
public class FileBotTree extends JTree implements TransferablePolicySupport {
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
public class FileBotTree extends JTree {
public FileBotTree() {
super(new DefaultTreeModel(new DefaultMutableTreeNode()));
@ -57,16 +51,6 @@ public class FileBotTree extends JTree implements TransferablePolicySupport {
}
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
}
public List<File> convertToList() {
TreeNode node = (TreeNode) getModel().getRoot();

View File

@ -10,7 +10,7 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import net.sourceforge.filebot.ui.transfer.FileTransferable;
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
import net.sourceforge.tuned.MessageBus;
import net.sourceforge.tuned.MessageHandler;
@ -18,18 +18,17 @@ import net.sourceforge.tuned.MessageHandler;
public class FileTransferableMessageHandler implements MessageHandler {
private final String name;
private final TransferablePolicySupport transferablePolicySupport;
private final TransferablePolicy transferablePolicy;
public FileTransferableMessageHandler(String name, TransferablePolicySupport transferablePolicySupport) {
public FileTransferableMessageHandler(String name, TransferablePolicy transferablePolicy) {
this.name = name;
this.transferablePolicySupport = transferablePolicySupport;
this.transferablePolicy = transferablePolicy;
}
@Override
public void handle(String topic, String... messages) {
// change panel
MessageBus.getDefault().publish("panel", name);
@ -50,6 +49,6 @@ public class FileTransferableMessageHandler implements MessageHandler {
}
}
transferablePolicySupport.getTransferablePolicy().handleTransferable(new FileTransferable(files), true);
transferablePolicy.handleTransferable(new FileTransferable(files), true);
}
}

View File

@ -62,7 +62,7 @@ public class AnalyzePanel extends FileBotPanel {
fileTreePanel.getFileTree().addPropertyChangeListener(FileTree.CONTENT_PROPERTY, fileTreeChangeListener);
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), fileTreePanel.getFileTree()));
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), fileTreePanel.getFileTree().getTransferablePolicy()));
}

View File

@ -20,6 +20,7 @@ import net.sourceforge.filebot.ui.FileBotTree;
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
import net.sourceforge.filebot.ui.transfer.FileTransferable;
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
class FileTree extends FileBotTree {
@ -29,13 +30,19 @@ class FileTree extends FileBotTree {
private PostProcessor postProcessor;
private final FileTreeTransferablePolicy transferablePolicy;
public FileTree() {
FileTreeTransferablePolicy transferPolicy = new FileTreeTransferablePolicy(this);
transferPolicy.addPropertyChangeListener(LOADING_PROPERTY, new LoadingPropertyChangeListener());
transferablePolicy = new FileTreeTransferablePolicy(this);
transferablePolicy.addPropertyChangeListener(LOADING_PROPERTY, new LoadingPropertyChangeListener());
setTransferablePolicy(transferPolicy);
setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(this), null));
setTransferHandler(new DefaultTransferHandler(new TransferablePolicyImportHandler(transferablePolicy), null));
}
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
}
@ -64,14 +71,14 @@ class FileTree extends FileBotTree {
public void load(List<File> files) {
FileTransferable tr = new FileTransferable(files);
if (getTransferablePolicy().accept(tr))
getTransferablePolicy().handleTransferable(tr, true);
if (transferablePolicy.accept(tr))
transferablePolicy.handleTransferable(tr, true);
}
@Override
public void clear() {
((FileTreeTransferablePolicy) getTransferablePolicy()).reset();
transferablePolicy.reset();
super.clear();
contentChanged();
@ -105,7 +112,7 @@ class FileTree extends FileBotTree {
}
private class PostProcessor extends SwingWorker<List<File>, Object> {
private class PostProcessor extends SwingWorker<List<File>, Void> {
@Override
protected List<File> doInBackground() throws Exception {

View File

@ -50,7 +50,7 @@ class FileTreePanel extends JPanel {
return fileTree;
}
private final LoadAction loadAction = new LoadAction(fileTree);
private final LoadAction loadAction = new LoadAction(fileTree.getTransferablePolicy());
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {

View File

@ -22,12 +22,6 @@ class FileTreeTransferablePolicy extends BackgroundFileTransferablePolicy<Defaul
}
@Override
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
@Override
protected void clear() {
tree.clear();

View File

@ -111,7 +111,7 @@ public class SplitPanel extends ToolPanel implements ChangeListener {
}
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
private class UpdateTask extends SwingWorker<DefaultTreeModel, Void> {
private final Collection<File> files;

View File

@ -59,7 +59,7 @@ public class TypePanel extends ToolPanel {
}
private class UpdateTask extends SwingWorker<DefaultTreeModel, Object> {
private class UpdateTask extends SwingWorker<DefaultTreeModel, Void> {
private final Collection<File> files;

View File

@ -26,12 +26,6 @@ class FileListTransferablePolicy extends FileTransferablePolicy {
}
@Override
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
@Override
protected void clear() {
list.getModel().clear();

View File

@ -39,7 +39,7 @@ public class ListPanel extends FileBotPanel {
private FileBotList list = new FileBotList(true, true, true);
private SaveAction saveAction = new SaveAction(list);
private LoadAction loadAction = new LoadAction(list);
private LoadAction loadAction = new LoadAction(list.getTransferablePolicy());
private JTextField textField = new JTextField(String.format("Name - %s", INDEX_VARIABLE), 25);
private SpinnerNumberModel fromSpinnerModel = new SpinnerNumberModel(1, 0, Integer.MAX_VALUE, 1);
@ -90,7 +90,7 @@ public class ListPanel extends FileBotPanel {
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("ENTER"), createAction);
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), list));
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), list.getTransferablePolicy()));
}

View File

@ -22,12 +22,6 @@ class FilesListTransferablePolicy extends FileTransferablePolicy {
}
@Override
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
@Override
protected void clear() {
model.clear();

View File

@ -111,7 +111,7 @@ class MatchAction extends AbstractAction {
}
private class BackgroundMatcher extends SwingWorker<List<Match>, Object> {
private class BackgroundMatcher extends SwingWorker<List<Match>, Void> {
private final RenameList primaryList;
private final RenameList secondaryList;

View File

@ -69,12 +69,6 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
}
@Override
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
@Override
protected void load(List<File> files) {
@ -146,7 +140,7 @@ class NamesListTransferablePolicy extends MultiTransferablePolicy {
protected void load(String text) {
List<ListEntry> entries = new ArrayList<ListEntry>();
String[] lines = text.split("\n");
String[] lines = text.split("\r?\n");
for (String line : lines) {

View File

@ -25,7 +25,7 @@ import net.sourceforge.filebot.ui.transfer.LoadAction;
class RenameList extends FileBotList {
public RenameList() {
super(true, false, true);
super(false, true, true);
Box buttons = Box.createHorizontalBox();
buttons.setBorder(new EmptyBorder(5, 5, 5, 5));
@ -86,7 +86,7 @@ class RenameList extends FileBotList {
}
};
protected final LoadAction loadAction = new LoadAction(this);
protected final LoadAction loadAction = new LoadAction(getTransferablePolicy());
private MouseAdapter dndReorderMouseAdapter = new MouseAdapter() {

View File

@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.search;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.FileBotList;
@ -19,11 +20,11 @@ public class EpisodeListPanel extends FileBotList {
public EpisodeListPanel() {
super(false, true, true, false);
super(true, true, false);
}
public FileBotTabComponent getTabComponent() {
public JComponent getTabComponent() {
return tabComponent;
}

View File

@ -10,7 +10,7 @@ import net.sourceforge.filebot.web.Episode;
import net.sourceforge.filebot.web.EpisodeListClient;
class FetchEpisodeListTask extends SwingWorker<List<Episode>, Object> {
class FetchEpisodeListTask extends SwingWorker<List<Episode>, Void> {
private final String showName;
private final EpisodeListClient searchEngine;

View File

@ -8,7 +8,6 @@ import java.awt.Window;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.net.URL;
import java.text.NumberFormat;
import java.util.ArrayList;
@ -181,41 +180,20 @@ public class SearchPanel extends FileBotPanel {
private final SaveAction saveAction = new SaveAction(null) {
private Saveable current;
@Override
public void actionPerformed(ActionEvent e) {
Component c = tabbedPane.getSelectedComponent();
if (c instanceof Saveable) {
current = (Saveable) c;
setSaveable((Saveable) c);
super.actionPerformed(e);
}
}
@Override
protected boolean isSaveable() {
return current.isSaveable();
}
@Override
protected String getDefaultFileName() {
return current.getDefaultFileName();
}
@Override
protected void save(File file) {
current.save(file);
current = null;
}
};
private class SearchTask extends SwingWorker<List<String>, Object> {
private class SearchTask extends SwingWorker<List<String>, Void> {
private String query;
private EpisodeListClient client;

View File

@ -10,7 +10,7 @@ import java.util.zip.CheckedInputStream;
import javax.swing.SwingWorker;
public class ChecksumComputationTask extends SwingWorker<Long, Object> {
public class ChecksumComputationTask extends SwingWorker<Long, Void> {
private static final int BUFFER_SIZE = 32 * 1024;

View File

@ -63,7 +63,7 @@ public class SfvPanel extends FileBotPanel {
// Shortcut DELETE
TunedUtil.registerActionForKeystroke(this, KeyStroke.getKeyStroke("pressed DELETE"), removeAction);
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), sfvTable));
MessageBus.getDefault().addMessageHandler(getPanelName(), new FileTransferableMessageHandler(getPanelName(), sfvTable.getTransferablePolicy()));
}
private final SaveAction saveAction = new SaveAction(sfvTable) {
@ -141,7 +141,7 @@ public class SfvPanel extends FileBotPanel {
}
};
private final LoadAction loadAction = new LoadAction(sfvTable);
private final LoadAction loadAction = new LoadAction(sfvTable.getTransferablePolicy());
private final AbstractAction clearAction = new AbstractAction("Clear", ResourceManager.getIcon("action.clear")) {

View File

@ -20,32 +20,28 @@ import net.sourceforge.filebot.FileFormat;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumTableModel.ChecksumTableModelEvent;
import net.sourceforge.filebot.ui.panel.sfv.renderer.ChecksumTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.renderer.StateIconTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.renderer.TextTableCellRenderer;
import net.sourceforge.filebot.ui.transfer.DefaultTransferHandler;
import net.sourceforge.filebot.ui.transfer.ExportHandler;
import net.sourceforge.filebot.ui.transfer.ImportHandler;
import net.sourceforge.filebot.ui.transfer.Saveable;
import net.sourceforge.filebot.ui.transfer.SaveableExportHandler;
import net.sourceforge.filebot.ui.transfer.TransferablePolicyImportHandler;
import net.sourceforge.filebot.ui.transfer.TransferablePolicySupport;
import net.sourceforge.filebot.ui.transferablepolicies.BackgroundFileTransferablePolicy;
import net.sourceforge.filebot.ui.transferablepolicies.NullTransferablePolicy;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
class SfvTable extends JTable implements Saveable {
private TransferablePolicy transferablePolicy = new NullTransferablePolicy();
private final SfvTransferablePolicy transferablePolicy;
public SfvTable() {
final ChecksumTableModel model = (ChecksumTableModel) getModel();
setFillsViewportHeight(true);
ChecksumTableModel model = (ChecksumTableModel) getModel();
transferablePolicy = new SfvTransferablePolicy(model);
setModel(model);
setFillsViewportHeight(true);
setAutoCreateRowSorter(true);
setAutoCreateColumnsFromModel(true);
setAutoResizeMode(AUTO_RESIZE_SUBSEQUENT_COLUMNS);
@ -54,18 +50,22 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
setRowHeight(20);
ImportHandler importHandler = new TransferablePolicyImportHandler(this);
ImportHandler importHandler = new TransferablePolicyImportHandler(transferablePolicy);
ExportHandler exportHandler = new SaveableExportHandler(this);
setTransferHandler(new DefaultTransferHandler(importHandler, exportHandler));
setDragEnabled(true);
setDefaultRenderer(ChecksumRow.State.class, new StateIconTableCellRenderer());
setDefaultRenderer(String.class, new TextTableCellRenderer());
setDefaultRenderer(Checksum.class, new ChecksumTableCellRenderer());
}
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
}
@Override
protected TableModel createDefaultDataModel() {
return new ChecksumTableModel();
@ -90,22 +90,12 @@ class SfvTable extends JTable implements TransferablePolicySupport, Saveable {
public void clear() {
((BackgroundFileTransferablePolicy<?>) getTransferablePolicy()).reset();
transferablePolicy.reset();
((ChecksumTableModel) getModel()).clear();
}
public TransferablePolicy getTransferablePolicy() {
return transferablePolicy;
}
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
public String getDefaultFileName() {
ChecksumTableModel model = (ChecksumTableModel) getModel();
File columnRoot = model.getChecksumColumnRoot(0);

View File

@ -27,12 +27,6 @@ class SfvTransferablePolicy extends BackgroundFileTransferablePolicy<ChecksumTab
}
@Override
protected boolean accept(File file) {
return file.isFile() || file.isDirectory();
}
@Override
protected void clear() {
tableModel.clear();

View File

@ -5,13 +5,14 @@ package net.sourceforge.filebot.ui.panel.sfv.renderer;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
public class ChecksumTableCellRenderer extends TextTableCellRenderer {
public class ChecksumTableCellRenderer extends DefaultTableCellRenderer {
private ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
private final ProgressBarTableCellRenderer progressBarRenderer = new ProgressBarTableCellRenderer();
@Override

View File

@ -6,10 +6,10 @@ import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Rectangle;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableCellRenderer;
import net.sourceforge.filebot.ui.panel.sfv.Checksum;
@ -17,17 +17,17 @@ import net.sourceforge.filebot.ui.panel.sfv.Checksum;
public class ProgressBarTableCellRenderer extends JPanel implements TableCellRenderer {
private JProgressBar progressBar = new JProgressBar(0, 100);
private final JProgressBar progressBar = new JProgressBar(0, 100);
public ProgressBarTableCellRenderer() {
super(new BorderLayout());
progressBar.setStringPainted(true);
add(progressBar, BorderLayout.CENTER);
int margin = 2;
setBorder(BorderFactory.createEmptyBorder(margin, margin, margin, margin));
setBorder(new EmptyBorder(2, 2, 2, 2));
}
@ -50,6 +50,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(long tm, int x, int y, int width, int height) {
}
@ -57,6 +58,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
/**
* Overridden for performance reasons.
*/
@Override
public void repaint(Rectangle r) {
}
@ -64,6 +66,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
/**
* Overridden for performance reasons.
*/
@Override
public void repaint() {
}
@ -71,6 +74,7 @@ public class ProgressBarTableCellRenderer extends JPanel implements TableCellRen
/**
* Overridden for performance reasons.
*/
@Override
public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
}

View File

@ -7,13 +7,14 @@ import java.awt.Component;
import javax.swing.Icon;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow;
import net.sourceforge.filebot.ui.panel.sfv.ChecksumRow.State;
public class StateIconTableCellRenderer extends TextTableCellRenderer {
public class StateIconTableCellRenderer extends DefaultTableCellRenderer {
private Icon warning = ResourceManager.getIcon("status.warning");
private Icon error = ResourceManager.getIcon("status.error");
@ -46,8 +47,6 @@ public class StateIconTableCellRenderer extends TextTableCellRenderer {
case UNKNOWN:
setIcon(unknown);
break;
default:
break;
}
return this;

View File

@ -1,27 +0,0 @@
package net.sourceforge.filebot.ui.panel.sfv.renderer;
import java.awt.Component;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
public class TextTableCellRenderer extends DefaultTableCellRenderer {
public TextTableCellRenderer() {
setVerticalAlignment(SwingConstants.CENTER);
setHorizontalAlignment(SwingConstants.LEFT);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, false, row, column);
return this;
}
}

View File

@ -20,4 +20,9 @@ public enum ArchiveType {
return UNKNOWN;
}
public String getExtension() {
return toString().toLowerCase();
}
}

View File

@ -11,7 +11,7 @@ import net.sourceforge.filebot.web.SubtitleClient;
import net.sourceforge.filebot.web.SubtitleDescriptor;
class FetchSubtitleListTask extends SwingWorker<List<? extends SubtitleDescriptor>, Object> {
class FetchSubtitleListTask extends SwingWorker<List<? extends SubtitleDescriptor>, Void> {
private final SubtitleClient client;
private final MovieDescriptor descriptor;

View File

@ -0,0 +1,121 @@
package net.sourceforge.filebot.ui.panel.subtitle;
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.SwingUtilities;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.FileBotTabComponent;
public class FileBotTab<T extends JComponent> extends JPanel {
private final FileBotTabComponent tabComponent = new FileBotTabComponent();
private final T component;
private ImageIcon icon;
private boolean loading = false;
public FileBotTab(T component) {
super(new BorderLayout());
this.component = component;
tabComponent.getCloseButton().addActionListener(closeAction);
add(component, BorderLayout.CENTER);
}
public void addTo(JTabbedPane tabbedPane) {
tabbedPane.addTab(this.getTitle(), this);
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(this), tabComponent);
}
public void close() {
if (!isClosed()) {
getTabbedPane().remove(this);
}
}
public boolean isClosed() {
JTabbedPane tabbedPane = getTabbedPane();
if (tabbedPane == null)
return true;
return getTabbedPane().indexOfComponent(this) < 0;
}
private JTabbedPane getTabbedPane() {
return (JTabbedPane) SwingUtilities.getAncestorOfClass(JTabbedPane.class, this);
}
public T getComponent() {
return component;
}
public FileBotTabComponent getTabComponent() {
return tabComponent;
}
public void setTitle(String title) {
tabComponent.setText(title);
}
public String getTitle() {
return tabComponent.getText();
}
public void setIcon(ImageIcon icon) {
this.icon = icon;
if (!loading) {
tabComponent.setIcon(icon);
}
}
public ImageIcon getIcon() {
return icon;
}
public void setLoading(boolean loading) {
this.loading = loading;
if (loading) {
tabComponent.setIcon(ResourceManager.getIcon("tab.loading"));
} else {
tabComponent.setIcon(icon);
}
}
private final ActionListener closeAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
close();
}
};
}

View File

@ -20,7 +20,7 @@ public class LanguageResolver {
/**
* Get the locale for a language.
* Get the {@link Locale} for a given language name (e.g. "german").
*
* @param languageName english name of the language
* @return the locale for this language or null if no locale for this language exists
@ -56,6 +56,13 @@ public class LanguageResolver {
}
/**
* Find the {@link Locale} for a given language name.
*
* @param languageName lower-case language name
* @return {@link Locale} for the given language, or null if no matching {@link Locale} is
* available
*/
private Locale findLocale(String languageName) {
for (Locale locale : Locale.getAvailableLocales()) {
if (locale.getDisplayLanguage(Locale.ENGLISH).toLowerCase().equals(languageName))

View File

@ -12,8 +12,6 @@ import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.SwingConstants;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.web.SubtitleDescriptor;
import net.sourceforge.tuned.ui.ColorTintImageFilter;
import net.sourceforge.tuned.ui.IconViewCellRenderer;
@ -44,18 +42,17 @@ public class SubtitleCellRenderer extends IconViewCellRenderer {
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
SubtitleDescriptor subtitle = (SubtitleDescriptor) value;
SubtitlePackage subtitle = (SubtitlePackage) value;
setText(subtitle.getName());
info1.setText(subtitle.getLanguageName());
info2.setText(subtitle.getAuthor());
icon = (ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLocale(subtitle.getLanguageName()).getLanguage()));
icon = subtitle.getLanguageIcon();
info1.setIcon(icon);
ImageIcon icon = ResourceManager.getArchiveIcon(subtitle.getArchiveType());
ImageIcon icon = subtitle.getArchiveIcon();
if (isSelected) {
setIcon(new ImageIcon(createImage(new FilteredImageSource(icon.getImage().getSource(), new ColorTintImageFilter(list.getSelectionBackground(), 0.5f)))));

View File

@ -0,0 +1,41 @@
package net.sourceforge.filebot.ui.panel.subtitle;
import java.util.List;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import net.sourceforge.filebot.web.SubtitleDescriptor;
import net.sourceforge.tuned.ui.SimpleListModel;
public class SubtitleDownloadPanel extends JPanel {
private final SubtitlePackagePanel packagePanel = new SubtitlePackagePanel();
public SubtitleDownloadPanel() {
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
add(packagePanel);
}
public SubtitlePackagePanel getPackagePanel() {
return packagePanel;
}
public void addSubtitleDescriptors(List<? extends SubtitleDescriptor> subtitleDescriptors) {
SimpleListModel model = new SimpleListModel();
for (SubtitleDescriptor subtitleDescriptor : subtitleDescriptors) {
model.add(new SubtitlePackage(subtitleDescriptor));
}
//TODO real add, not setModel
packagePanel.setModel(model);
}
}

View File

@ -6,7 +6,7 @@ import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.web.SubtitleDescriptor;
@ -17,13 +17,20 @@ public class SubtitlePackage {
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private DownloadTask downloadTask = null;
private final SubtitleDescriptor subtitleDescriptor;
private final ImageIcon archiveIcon;
private final ImageIcon languageIcon;
private DownloadTask downloadTask;
public SubtitlePackage(SubtitleDescriptor subtitleDescriptor) {
this.subtitleDescriptor = subtitleDescriptor;
archiveIcon = ResourceManager.getArchiveIcon(subtitleDescriptor.getArchiveType());
languageIcon = ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLanguageCode(subtitleDescriptor.getLanguageName()));
}
@ -37,8 +44,8 @@ public class SubtitlePackage {
}
public Icon getArchiveIcon() {
return ResourceManager.getArchiveIcon(getArchiveType().toString());
public ImageIcon getArchiveIcon() {
return archiveIcon;
}
@ -47,8 +54,8 @@ public class SubtitlePackage {
}
public Icon getLanguageIcon() {
return ResourceManager.getFlagIcon(LanguageResolver.getDefault().getLanguageCode(getLanguageName()));
public ImageIcon getLanguageIcon() {
return languageIcon;
}
@ -57,7 +64,7 @@ public class SubtitlePackage {
throw new IllegalStateException("Download has been started already");
downloadTask = subtitleDescriptor.createDownloadTask();
downloadTask.addPropertyChangeListener(new DownloadTaskPropertyChangeRelay());
downloadTask.addPropertyChangeListener(new DownloadTaskPropertyChangeAdapter());
downloadTask.execute();
}
@ -81,7 +88,7 @@ public class SubtitlePackage {
}
private class DownloadTaskPropertyChangeRelay implements PropertyChangeListener {
private class DownloadTaskPropertyChangeAdapter implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {

View File

@ -20,25 +20,23 @@ import java.util.TreeSet;
import javax.swing.Icon;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
import javax.swing.JToolTip;
import javax.swing.ListModel;
import net.sourceforge.filebot.Settings;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.web.SubtitleDescriptor;
import net.sourceforge.tuned.ui.IconViewPanel;
import net.sourceforge.tuned.ui.SimpleListModel;
public class SubtitleViewPanel extends IconViewPanel {
public class SubtitlePackagePanel extends IconViewPanel {
private final JPanel languageFilterPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 1));
private ListModel unfilteredModel = new SimpleListModel();
private JPanel languageFilterPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 5, 1));
private Map<String, Boolean> languageFilterSelection = new TreeMap<String, Boolean>(String.CASE_INSENSITIVE_ORDER);
public SubtitleViewPanel() {
public SubtitlePackagePanel() {
setCellRenderer(new SubtitleCellRenderer());
languageFilterPanel.setOpaque(false);
@ -71,7 +69,7 @@ public class SubtitleViewPanel extends IconViewPanel {
SortedSet<String> languages = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
for (int i = 0; i < unfilteredModel.getSize(); i++) {
SubtitleDescriptor subtitle = (SubtitleDescriptor) unfilteredModel.getElementAt(i);
SubtitlePackage subtitle = (SubtitlePackage) unfilteredModel.getElementAt(i);
languages.add(subtitle.getLanguageName());
}
@ -90,7 +88,7 @@ public class SubtitleViewPanel extends IconViewPanel {
SimpleListModel model = new SimpleListModel();
for (int i = 0; i < unfilteredModel.getSize(); i++) {
SubtitleDescriptor subtitle = (SubtitleDescriptor) unfilteredModel.getElementAt(i);
SubtitlePackage subtitle = (SubtitlePackage) unfilteredModel.getElementAt(i);
if (isLanguageSelected(subtitle.getLanguageName())) {
model.add(subtitle);
@ -106,6 +104,12 @@ public class SubtitleViewPanel extends IconViewPanel {
}
public void setLanguageSelected(String language, boolean selected) {
languageFilterSelection.put(language, selected);
Settings.getSettings().putBooleanMapEntry(Settings.SUBTITLE_LANGUAGE, language, selected);
}
private LanguageFilterButton createLanguageFilterButton(String language) {
Locale locale = LanguageResolver.getDefault().getLocale(language);
@ -132,8 +136,7 @@ public class SubtitleViewPanel extends IconViewPanel {
public void itemStateChanged(ItemEvent e) {
boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
languageFilterSelection.put(language, selected);
Settings.getSettings().putBooleanMapEntry(Settings.SUBTITLE_LANGUAGE, language, selected);
setLanguageSelected(language, selected);
updateFilteredModel();
}
@ -170,19 +173,15 @@ public class SubtitleViewPanel extends IconViewPanel {
protected void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
AlphaComposite composite = AlphaComposite.SrcOver.derive(isSelected() ? 1.0f : 0.2f);
g2d.setComposite(composite);
// make transparent if not selected
if (!isSelected()) {
AlphaComposite composite = AlphaComposite.SrcOver.derive(0.2f);
g2d.setComposite(composite);
}
super.paintComponent(g2d);
}
}
@Override
public JToolTip createToolTip() {
System.out.println("SubtitleViewPanel.createToolTip()");
return super.createToolTip();
}
}

View File

@ -30,7 +30,6 @@ import net.sourceforge.filebot.FileBotUtil;
import net.sourceforge.filebot.Settings;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.filebot.ui.FileBotPanel;
import net.sourceforge.filebot.ui.FileBotTabComponent;
import net.sourceforge.filebot.ui.HistoryPanel;
import net.sourceforge.filebot.ui.MessageManager;
import net.sourceforge.filebot.ui.SelectDialog;
@ -133,7 +132,7 @@ public class SubtitlePanel extends FileBotPanel {
};
private class SearchTask extends SwingWorker<List<MovieDescriptor>, Object> {
private class SearchTask extends SwingWorker<List<MovieDescriptor>, Void> {
private final String query;
private final SubtitleClient client;
@ -155,26 +154,27 @@ public class SubtitlePanel extends FileBotPanel {
private class SearchTaskListener extends SwingWorkerPropertyChangeAdapter {
private SubtitleViewPanel subtitleSearchResultPanel;
private FileBotTabComponent tabComponent;
private FileBotTab<SubtitleDownloadPanel> downloadPanel;
@Override
public void started(PropertyChangeEvent evt) {
SearchTask task = (SearchTask) evt.getSource();
subtitleSearchResultPanel = new SubtitleViewPanel();
tabComponent = new FileBotTabComponent(task.query, ResourceManager.getIcon("tab.loading"));
downloadPanel = new FileBotTab<SubtitleDownloadPanel>(new SubtitleDownloadPanel());
tabbedPane.addTab(task.query, subtitleSearchResultPanel);
tabbedPane.setTabComponentAt(tabbedPane.indexOfComponent(subtitleSearchResultPanel), tabComponent);
downloadPanel.setTitle(task.query);
downloadPanel.setLoading(true);
downloadPanel.setIcon(task.client.getIcon());
downloadPanel.addTo(tabbedPane);
}
@Override
public void done(PropertyChangeEvent evt) {
// tab might have been closed
if (tabbedPane.indexOfComponent(subtitleSearchResultPanel) < 0)
if (downloadPanel.isClosed())
return;
SearchTask searchTask = (SearchTask) evt.getSource();
@ -185,18 +185,26 @@ public class SubtitlePanel extends FileBotPanel {
MovieDescriptor descriptor = selectDescriptor(desriptors, searchTask.client);
if (descriptor == null) {
// user canceled selection, or no subtitles available
if (desriptors.isEmpty()) {
MessageManager.showWarning(String.format("\"%s\" has not been found.", searchTask.query));
}
tabbedPane.remove(subtitleSearchResultPanel);
downloadPanel.close();
return;
}
fetchSubtitles(descriptor, searchTask.client);
searchFieldCompletion.addTerm(descriptor.getTitle());
Settings.getSettings().putStringList(Settings.SUBTITLE_HISTORY, searchFieldCompletion.getTerms());
downloadPanel.setTitle(descriptor.getTitle());
FetchSubtitleListTask fetchListTask = new FetchSubtitleListTask(descriptor, searchTask.client);
fetchListTask.addPropertyChangeListener(new FetchSubtitleListTaskListener(downloadPanel));
fetchListTask.execute();
} catch (Exception e) {
tabbedPane.remove(subtitleSearchResultPanel);
downloadPanel.close();
Throwable cause = FileBotUtil.getRootCause(e);
@ -224,42 +232,27 @@ public class SubtitlePanel extends FileBotPanel {
selectDialog.setIconImage(client.getIcon().getImage());
selectDialog.setVisible(true);
// selected value or null if cancelled by the user
// selected value or null if canceled by the user
return selectDialog.getSelectedValue();
}
private void fetchSubtitles(MovieDescriptor descriptor, SubtitleClient client) {
Settings.getSettings().putStringList(Settings.SUBTITLE_HISTORY, searchFieldCompletion.getTerms());
searchFieldCompletion.addTerm(descriptor.getTitle());
tabComponent.setText(descriptor.getTitle());
FetchSubtitleListTask fetchListTask = new FetchSubtitleListTask(descriptor, client);
fetchListTask.addPropertyChangeListener(new FetchSubtitleListTaskListener(subtitleSearchResultPanel, tabComponent));
fetchListTask.execute();
}
}
private class FetchSubtitleListTaskListener extends SwingWorkerPropertyChangeAdapter {
private final SubtitleViewPanel subtitleSearchResultPanel;
private final FileBotTabComponent tabComponent;
private final FileBotTab<SubtitleDownloadPanel> downloadPanel;
public FetchSubtitleListTaskListener(SubtitleViewPanel subtitleSearchResultPanel, FileBotTabComponent tabComponent) {
this.subtitleSearchResultPanel = subtitleSearchResultPanel;
this.tabComponent = tabComponent;
public FetchSubtitleListTaskListener(FileBotTab<SubtitleDownloadPanel> downloadPanel) {
this.downloadPanel = downloadPanel;
}
@Override
public void done(PropertyChangeEvent evt) {
// tab might have been closed
if (tabbedPane.indexOfComponent(subtitleSearchResultPanel) < 0)
if (downloadPanel.isClosed())
return;
FetchSubtitleListTask task = (FetchSubtitleListTask) evt.getSource();
@ -272,17 +265,17 @@ public class SubtitlePanel extends FileBotPanel {
historyPanel.add(task.getDescriptor().toString(), null, task.getClient().getIcon(), info, NumberFormat.getInstance().format(task.getDuration()) + " ms");
if (subtitleDescriptors.isEmpty()) {
tabbedPane.remove(subtitleSearchResultPanel);
MessageManager.showWarning(info);
downloadPanel.close();
return;
}
tabComponent.setIcon(task.getClient().getIcon());
downloadPanel.setLoading(false);
//TODO icon view
//TODO sysout
System.out.println(subtitleDescriptors);
downloadPanel.getComponent().getPackagePanel().setTitle(info);
downloadPanel.getComponent().addSubtitleDescriptors(subtitleDescriptors);
} catch (Exception e) {
tabbedPane.remove(subtitleSearchResultPanel);
downloadPanel.close();
MessageManager.showWarning(FileBotUtil.getRootCause(e).getMessage());
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);

View File

@ -20,12 +20,12 @@ public class Unrar {
private static final int sleepInterval = 50;
public static void extractFiles(File archive, File destination) throws Exception {
public static void extractFiles(File archiveFile, File destinationFolder) throws Exception {
if (command == null) {
throw new IllegalStateException("Unrar could not be initialized");
}
Process process = command.execute(archive, destination);
Process process = command.execute(archiveFile, destinationFolder);
int counter = 0;
@ -117,7 +117,15 @@ public class Unrar {
ProcessBuilder builder = new ProcessBuilder(executable, "x", "-y", archive.getAbsolutePath());
builder.directory(workingDirectory);
return builder.start();
Process process = builder.start();
// make sure process is non-interactive
// e.g. if input stream is not closed 7z.exe sometimes doesn't exit
process.getInputStream().close();
process.getOutputStream().close();
process.getErrorStream().close();
return process;
}

View File

@ -92,5 +92,26 @@ public class DefaultTransferHandler extends TransferHandler {
if (clipboardHandler != null)
clipboardHandler.exportToClipboard(comp, clip, action);
}
public void setImportHandler(ImportHandler importHandler) {
this.importHandler = importHandler;
}
public void setExportHandler(ExportHandler exportHandler) {
this.exportHandler = exportHandler;
}
public void setClipboardHandler(ClipboardHandler clipboardHandler) {
this.clipboardHandler = clipboardHandler;
}
}

View File

@ -13,19 +13,19 @@ import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
public class LoadAction extends AbstractAction {
private TransferablePolicySupport transferablePolicySupport;
private final TransferablePolicy transferablePolicy;
public LoadAction(TransferablePolicySupport transferablePolicySupport) {
public LoadAction(TransferablePolicy transferablePolicy) {
super("Load", ResourceManager.getIcon("action.load"));
this.transferablePolicySupport = transferablePolicySupport;
this.transferablePolicy = transferablePolicy;
}
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.setFileFilter(new TransferablePolicyFileFilter(transferablePolicySupport.getTransferablePolicy()));
chooser.setFileFilter(new TransferablePolicyFileFilter(transferablePolicy));
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
chooser.setMultiSelectionEnabled(true);
@ -35,8 +35,6 @@ public class LoadAction extends AbstractAction {
FileTransferable transferable = new FileTransferable(chooser.getSelectedFiles());
TransferablePolicy transferablePolicy = transferablePolicySupport.getTransferablePolicy();
boolean add = ((e.getModifiers() & ActionEvent.CTRL_MASK) != 0);
if (transferablePolicy.accept(transferable))

View File

@ -43,6 +43,11 @@ public class SaveAction extends AbstractAction {
}
protected void setSaveable(Saveable saveable) {
this.saveable = saveable;
}
public void actionPerformed(ActionEvent e) {
if (!isSaveable())
return;

View File

@ -13,7 +13,7 @@ import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
public class TransferablePolicyFileFilter extends FileFilter {
private TransferablePolicy transferablePolicy;
private final TransferablePolicy transferablePolicy;
public TransferablePolicyFileFilter(TransferablePolicy transferablePolicy) {

View File

@ -10,15 +10,16 @@ import java.util.logging.Logger;
import javax.swing.TransferHandler;
import javax.swing.TransferHandler.TransferSupport;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
public class TransferablePolicyImportHandler implements ImportHandler {
private TransferablePolicySupport transferablePolicySupport;
private final TransferablePolicy transferablePolicy;
public TransferablePolicyImportHandler(TransferablePolicySupport transferablePolicySupport) {
this.transferablePolicySupport = transferablePolicySupport;
public TransferablePolicyImportHandler(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
private boolean canImportCache = false;
@ -32,7 +33,7 @@ public class TransferablePolicyImportHandler implements ImportHandler {
Transferable t = support.getTransferable();
try {
canImportCache = transferablePolicySupport.getTransferablePolicy().accept(t);
canImportCache = transferablePolicy.accept(t);
} catch (InvalidDnDOperationException e) {
// for some reason the last transferable has no drop current
}
@ -51,7 +52,7 @@ public class TransferablePolicyImportHandler implements ImportHandler {
Transferable t = support.getTransferable();
try {
transferablePolicySupport.getTransferablePolicy().handleTransferable(t, add);
transferablePolicy.handleTransferable(t, add);
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
}

View File

@ -1,11 +0,0 @@
package net.sourceforge.filebot.ui.transfer;
import net.sourceforge.filebot.ui.transferablepolicies.TransferablePolicy;
public interface TransferablePolicySupport {
public TransferablePolicy getTransferablePolicy();
}

View File

@ -85,7 +85,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
}
private class BackgroundWorker extends SwingWorker<Object, V> {
private class BackgroundWorker extends SwingWorker<Void, V> {
private final List<File> files;
@ -96,7 +96,7 @@ public abstract class BackgroundFileTransferablePolicy<V> extends FileTransferab
@Override
protected Object doInBackground() {
protected Void doInBackground() {
load(files);
return null;

View File

@ -110,7 +110,7 @@ public abstract class FileTransferablePolicy implements TransferablePolicy {
protected boolean accept(File file) {
return false;
return file.isFile() || file.isDirectory();
}

View File

@ -0,0 +1,44 @@
package net.sourceforge.filebot.ui.transferablepolicies;
import java.awt.datatransfer.Transferable;
public class MutableTransferablePolicy implements TransferablePolicy {
private TransferablePolicy transferablePolicy = null;
public void setTransferablePolicy(TransferablePolicy transferablePolicy) {
this.transferablePolicy = transferablePolicy;
}
@Override
public boolean accept(Transferable tr) {
if (transferablePolicy == null)
return false;
return transferablePolicy.accept(tr);
}
@Override
public String getDescription() {
if (transferablePolicy == null)
return null;
return transferablePolicy.getDescription();
}
@Override
public void handleTransferable(Transferable tr, boolean add) {
if (transferablePolicy == null)
return;
transferablePolicy.handleTransferable(tr, add);
}
}

View File

@ -12,16 +12,18 @@ import javax.swing.ImageIcon;
public abstract class EpisodeListClient {
private static final List<EpisodeListClient> registry = new ArrayList<EpisodeListClient>();
static {
registry.add(new TvdotcomClient());
registry.add(new AnidbClient());
registry.add(new TVRageClient());
}
private static List<EpisodeListClient> registry;
public static List<EpisodeListClient> getAvailableEpisodeListClients() {
public static synchronized List<EpisodeListClient> getAvailableEpisodeListClients() {
if (registry == null) {
registry = new ArrayList<EpisodeListClient>(3);
registry.add(new TvdotcomClient());
registry.add(new AnidbClient());
registry.add(new TVRageClient());
}
return Collections.unmodifiableList(registry);
}

View File

@ -2,33 +2,20 @@
package net.sourceforge.filebot.web;
import java.net.URL;
public class MovieDescriptor {
private final String title;
private final Integer imdbId;
private final Integer year;
private final URL imdbUrl;
public MovieDescriptor(String description) {
this(description, null);
public MovieDescriptor(String title) {
this(title, null);
}
public MovieDescriptor(String description, Integer imdbId) {
this(description, imdbId, null, null);
}
public MovieDescriptor(String title, Integer imdbId, Integer year, URL imdbUrl) {
public MovieDescriptor(String title, Integer imdbId) {
this.title = title;
this.imdbId = imdbId;
this.year = year;
this.imdbUrl = imdbUrl;
}
@ -42,21 +29,9 @@ public class MovieDescriptor {
}
public Integer getYear() {
return year;
}
public URL getImdbUrl() {
return imdbUrl;
}
@Override
public String toString() {
if (year == null)
return title;
return String.format("%s (%d)", title, year);
return title;
}
}

View File

@ -35,9 +35,9 @@ public class OpenSubtitlesClient {
* </tr>
* </table>
*/
private String url = "http://www.opensubtitles.org/xml-rpc";
private final String url = "http://www.opensubtitles.org/xml-rpc";
private String useragent;
private final String useragent;
private String token = null;
@ -57,6 +57,13 @@ public class OpenSubtitlesClient {
}
/**
* Login as user and use english as language
*
* @param username
* @param password
* @throws XmlRpcFault
*/
public void login(String username, String password) throws XmlRpcFault {
login(username, password, "en");
}
@ -85,19 +92,20 @@ public class OpenSubtitlesClient {
/**
* This will logout user (ends session id). Good call this function is before ending
* (closing) clients program.
*
* @throws XmlRpcFault
*/
@SuppressWarnings("unchecked")
public synchronized void logout() {
// anonymous users will always get a 401 Unauthorized when trying to logout
public synchronized void logout() throws XmlRpcFault {
try {
Map<String, String> response = (Map<String, String>) invoke("LogOut", token);
checkStatus(response.get("status"));
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, "Exception while deactivating session", e);
invoke("LogOut", token);
// anonymous users will always get a 401 Unauthorized when trying to logout
// do not check status for logout response
// checkStatus(response.get("status"));
} finally {
token = null;
}
token = null;
}

View File

@ -13,7 +13,7 @@ import net.sourceforge.filebot.resources.ResourceManager;
/**
* Client for the OpenSubtitles XML-RPC API.
* {@link SubtitleClient} for OpenSubtitles.
*
*/
public class OpenSubtitlesSubtitleClient extends SubtitleClient {
@ -32,7 +32,7 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
@Override
public List<MovieDescriptor> search(String query) throws Exception {
activate();
login();
return client.searchMoviesOnIMDB(query);
}
@ -40,39 +40,45 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
@Override
public List<OpenSubtitlesSubtitleDescriptor> getSubtitleList(MovieDescriptor descriptor) throws Exception {
activate();
login();
return client.searchSubtitles(descriptor.getImdbId());
}
private synchronized void activate() {
try {
if (!client.isLoggedOn()) {
client.loginAnonymous();
}
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, e.toString(), e);
private synchronized void login() throws Exception {
if (!client.isLoggedOn()) {
client.loginAnonymous();
}
logoutTimer.restart();
}
private synchronized void logout() {
logoutTimer.stop();
if (client.isLoggedOn()) {
try {
client.logout();
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.SEVERE, "Exception while deactivating session", e);
}
}
}
private final Runnable doLogout = new Runnable() {
@Override
public void run() {
logoutTimer.stop();
if (client.isLoggedOn()) {
client.logout();
}
logout();
}
};
private class LogoutTimer {
private static final int LOGOUT_DELAY = 15000; // 12 minutes
private final long LOGOUT_DELAY = 12 * 60 * 1000; // 12 minutes
private Timer daemon = null;
private LogoutTimerTask currentTimerTask = null;
@ -85,7 +91,6 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
if (currentTimerTask != null) {
currentTimerTask.cancel();
daemon.purge();
}
currentTimerTask = new LogoutTimerTask();
@ -109,7 +114,7 @@ public class OpenSubtitlesSubtitleClient extends SubtitleClient {
@Override
public void run() {
doLogout.run();
logout();
};
};
}

View File

@ -17,6 +17,7 @@ import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.filebot.FileFormat;
import net.sourceforge.filebot.resources.ResourceManager;
import net.sourceforge.tuned.XPathUtil;
@ -71,8 +72,7 @@ public class SubsceneSubtitleClient extends SubtitleClient {
Document dom = HtmlUtil.getHtmlDocument(url);
String downloadPath = XPathUtil.selectString("id('aspnetForm')/@action", dom);
String viewstate = XPathUtil.selectString("id('__VIEWSTATE')/@value", dom);
Pattern hrefPattern = Pattern.compile("javascript:Subtitle\\((\\d+), '(\\w+)', '0', '(\\d+)'\\);");
List<Node> nodes = XPathUtil.selectNodes("//TABLE[@class='filmSubtitleList']//A[@id]//ancestor::TR", dom);
@ -88,15 +88,20 @@ public class SubsceneSubtitleClient extends SubtitleClient {
String name = XPathUtil.selectString("./SPAN[2]", linkNode);
int numberOfCDs = Integer.parseInt(XPathUtil.selectString("./TD[2]", node));
boolean hearingImpaired = XPathUtil.selectFirstNode("./TD[3]/*[@id='imgEar']", node) != null;
boolean hearingImpaired = (XPathUtil.selectFirstNode("./TD[3]/*[@id='imgEar']", node) != null);
String author = XPathUtil.selectString("./TD[4]", node);
URL downloadUrl = new URL("http", host, downloadPath);
Matcher matcher = hrefPattern.matcher(href);
Map<String, String> downloadParameters = parseParameters(href);
downloadParameters.put("__VIEWSTATE", viewstate);
if (!matcher.matches())
throw new IllegalArgumentException("Cannot extract download parameters: " + href);
list.add(new SubsceneSubtitleDescriptor(name, lang, numberOfCDs, author, hearingImpaired, downloadUrl, downloadParameters));
String subtitleId = matcher.group(1);
String typeId = matcher.group(2);
URL downloadUrl = getDownloadUrl(url, subtitleId, typeId);
list.add(new SubsceneSubtitleDescriptor(name, lang, numberOfCDs, author, hearingImpaired, typeId, downloadUrl, url));
} catch (Exception e) {
Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).log(Level.WARNING, "Cannot parse subtitle node", e);
}
@ -106,19 +111,11 @@ public class SubsceneSubtitleClient extends SubtitleClient {
}
private Map<String, String> parseParameters(String href) {
Matcher matcher = Pattern.compile("javascript:Subtitle\\((\\d+), '(\\w+)', '0', '(\\d+)'\\);").matcher(href);
private URL getDownloadUrl(URL referer, String subtitleId, String typeId) throws MalformedURLException {
String basePath = FileFormat.getNameWithoutExtension(referer.getFile());
String path = String.format("%s-dlpath-%s/%s.zipx", basePath, subtitleId, typeId);
if (!matcher.matches())
throw new IllegalArgumentException("Cannot extract download parameters: " + href);
Map<String, String> map = new HashMap<String, String>();
map.put("subtitleId", matcher.group(1));
map.put("typeId", matcher.group(2));
map.put("filmId", matcher.group(3));
return map;
return new URL(referer.getProtocol(), referer.getHost(), path);
}

View File

@ -3,7 +3,6 @@ package net.sourceforge.filebot.web;
import java.net.URL;
import java.util.Map;
import net.sourceforge.tuned.DownloadTask;
@ -16,19 +15,23 @@ public class SubsceneSubtitleDescriptor implements SubtitleDescriptor {
private final String author;
private final boolean hearingImpaired;
private final Map<String, String> downloadParameters;
private final String typeId;
private final URL downloadUrl;
private final URL referer;
public SubsceneSubtitleDescriptor(String title, String language, int numberOfCDs, String author, boolean hearingImpaired, URL downloadUrl, Map<String, String> downloadParameters) {
public SubsceneSubtitleDescriptor(String title, String language, int numberOfCDs, String author, boolean hearingImpaired, String typeId, URL downloadUrl, URL referer) {
this.title = title;
this.language = language;
this.numberOfCDs = numberOfCDs;
this.author = author;
this.hearingImpaired = hearingImpaired;
this.typeId = typeId;
this.downloadUrl = downloadUrl;
this.downloadParameters = downloadParameters;
this.referer = referer;
}
@ -60,13 +63,16 @@ public class SubsceneSubtitleDescriptor implements SubtitleDescriptor {
@Override
public DownloadTask createDownloadTask() {
return new DownloadTask(downloadUrl, downloadParameters);
DownloadTask downloadTask = new DownloadTask(downloadUrl);
downloadTask.setRequestHeader("Referer", referer.toString());
return downloadTask;
}
@Override
public String getArchiveType() {
return downloadParameters.get("typeId");
return typeId;
}

View File

@ -11,15 +11,17 @@ import javax.swing.ImageIcon;
public abstract class SubtitleClient {
private static final List<SubtitleClient> registry = new ArrayList<SubtitleClient>();
static {
registry.add(new OpenSubtitlesSubtitleClient());
registry.add(new SubsceneSubtitleClient());
}
private static List<SubtitleClient> registry;
public static List<SubtitleClient> getAvailableSubtitleClients() {
public static synchronized List<SubtitleClient> getAvailableSubtitleClients() {
if (registry == null) {
registry = new ArrayList<SubtitleClient>(2);
registry.add(new OpenSubtitlesSubtitleClient());
registry.add(new SubsceneSubtitleClient());
}
return Collections.unmodifiableList(registry);
}

View File

@ -13,6 +13,8 @@ import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -20,7 +22,7 @@ import java.util.logging.Logger;
import javax.swing.SwingWorker;
public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
public class DownloadTask extends SwingWorker<ByteBuffer, Void> {
public static final String DOWNLOAD_STATE = "download state";
public static final String DOWNLOAD_PROGRESS = "download progress";
@ -30,32 +32,44 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
PENDING,
CONNECTING,
DOWNLOADING,
DONE;
DONE
}
private static final int BUFFER_SIZE = 4 * 1024;
private final int BUFFER_SIZE = 4 * 1024;
private URL url;
private ByteBuffer postdata = null;
private ByteBuffer postdata;
private long size = -1;
private long bytesRead = 0;
private DownloadState state = DownloadState.PENDING;
private final Map<String, String> requestHeaders = new HashMap<String, String>();
private final Map<String, String> responseHeaders = new HashMap<String, String>();
public DownloadTask(URL url) {
this.url = url;
this(url, null);
}
public DownloadTask(URL url, ByteBuffer postdata) {
public DownloadTask(URL url, Map<String, String> postParameters) {
this.url = url;
this.postdata = postdata;
if (postParameters != null) {
this.postdata = encodeParameters(postParameters);
}
}
public DownloadTask(URL url, Map<String, String> postdata) {
this(url, encodeParameters(postdata));
protected HttpURLConnection createConnection() throws Exception {
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
for (String key : requestHeaders.keySet()) {
connection.addRequestProperty(key, requestHeaders.get(key));
}
return connection;
}
@ -63,7 +77,7 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
protected ByteBuffer doInBackground() throws Exception {
setDownloadState(DownloadState.CONNECTING);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
HttpURLConnection connection = createConnection();
if (postdata != null) {
connection.setRequestMethod("POST");
@ -75,31 +89,39 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
size = connection.getContentLength();
for (String key : connection.getHeaderFields().keySet()) {
responseHeaders.put(key, connection.getHeaderField(key));
}
setDownloadState(DownloadState.DOWNLOADING);
InputStream in = connection.getInputStream();
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
ByteArrayOutputStream out = new ByteArrayOutputStream(Math.max((int) size, BUFFER_SIZE));
byte[] buffer = new byte[BUFFER_SIZE];
int len = 0;
try {
while (((len = in.read(buffer)) > 0) && !isCancelled()) {
while (((len = in.read(buffer)) >= 0) && !isCancelled()) {
out.write(buffer, 0, len);
bytesRead += len;
getPropertyChangeSupport().firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
firePropertyChange(DOWNLOAD_PROGRESS, null, bytesRead);
if (isDownloadSizeKnown()) {
setProgress((int) ((bytesRead * 100) / size));
}
}
} catch (IOException e) {
// IOException (Premature EOF) is always thrown when the size of
// the response body is not known in advance, so we ignore it
if (isSizeKnown())
if (isDownloadSizeKnown())
throw e;
} finally {
in.close();
out.close();
connection.disconnect();
}
setDownloadState(DownloadState.DONE);
@ -107,9 +129,9 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
}
private void setDownloadState(DownloadState state) {
protected void setDownloadState(DownloadState state) {
this.state = state;
getPropertyChangeSupport().firePropertyChange(DOWNLOAD_STATE, null, state);
firePropertyChange(DOWNLOAD_STATE, null, state);
}
@ -118,22 +140,37 @@ public class DownloadTask extends SwingWorker<ByteBuffer, Object> {
}
public URL getUrl() {
return url;
}
public long getBytesRead() {
return bytesRead;
}
public boolean isSizeKnown() {
public boolean isDownloadSizeKnown() {
return size >= 0;
}
public long getSize() {
public long getDownloadSize() {
return size;
}
private static ByteBuffer encodeParameters(Map<String, String> parameters) {
public void setRequestHeader(String name, String value) {
requestHeaders.put(name, value);
}
public Map<String, String> getResponseHeaders() {
return Collections.unmodifiableMap(responseHeaders);
}
protected static ByteBuffer encodeParameters(Map<String, String> parameters) {
StringBuilder sb = new StringBuilder();
int i = 0;

View File

@ -42,8 +42,6 @@ public class TemporaryFolder {
for (TemporaryFolder folder : folders.values()) {
folder.delete();
}
folders.clear();
}
}
});
@ -57,6 +55,13 @@ public class TemporaryFolder {
}
/**
* Create an empty file in this temporary folder
*
* @param name name of the file
* @return newly created file
* @throws IOException if an I/O error occurred
*/
public File createFile(String name) throws IOException {
if (!root.exists()) {
root.mkdir();
@ -69,15 +74,37 @@ public class TemporaryFolder {
}
public void deleteFile(String name) {
File file = new File(root, name);
if (file.exists()) {
file.delete();
/**
* Creates an empty file in this temporary folder, using the given prefix and suffix to
* generate its name.
*
* @param prefix The prefix string to be used in generating the file's name; must be at
* least three characters long
* @param suffix The suffix string to be used in generating the file's name; may be null,
* in which case the suffix ".tmp" will be used
* @return An abstract pathname denoting a newly-created empty file
* @throws IOException If a file could not be created
* @see File#createTempFile(String, String)
*/
public File createFile(String prefix, String suffix) throws IOException {
if (!root.exists()) {
root.mkdir();
}
return File.createTempFile(prefix, suffix, root);
}
public boolean deleteFile(String name) {
return new File(root, name).delete();
}
/**
* Retrieve the {@link File} object for this {@link TemporaryFolder}
*
* @return the {@link File} object for this {@link TemporaryFolder}
*/
public File getFolder() {
return root;
}

View File

@ -1,51 +0,0 @@
package net.sourceforge.tuned;
import java.util.TreeMap;
public class TimeIntervalFormat {
private static TreeMap<Long, String> unitMap = new TreeMap<Long, String>();
static {
unitMap.put(1L, "ms");
unitMap.put(1000L, "s");
unitMap.put(60 * 1000L, "m");
unitMap.put(60 * 60 * 1000L, "h");
}
public static String format(long millis, boolean zerounits) {
boolean negativ = false;
if (millis < 0) {
millis = Math.abs(millis);
negativ = true;
}
StringBuilder sb = new StringBuilder();
for (long unitBaseTime : unitMap.descendingKeySet()) {
int quotient = (int) (millis / unitBaseTime);
boolean isLastKey = (unitBaseTime == unitMap.firstKey());
if (zerounits || (quotient != 0) || isLastKey) {
sb.append(quotient + unitMap.get(unitBaseTime));
if (!isLastKey)
;
sb.append(" ");
}
millis -= quotient * unitBaseTime;
}
if (negativ)
sb.insert(0, "-");
return sb.toString();
}
}

View File

@ -1,6 +1,10 @@
package net.sourceforge.tuned.ui;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
@ -26,14 +30,15 @@ public class ProgressIndicator extends JComponent {
private int indeterminateShapeCount = 1;
private float progressStrokeWidth = 4.5f;
private float remainingStrokeWidth = 2.5f;
private float remainingStrokeWidth = 2f;
private Stroke progressStroke = new BasicStroke(progressStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
private Stroke remainingStroke = new BasicStroke(remainingStrokeWidth, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND);
private Color progressColor = Color.orange;
private Color remainingColor = new Color(0f, 0f, 0f, 0.25f);
private Color textColor = new Color(42, 42, 42);
private Color textColor = new Color(0x5F5F5F);
private boolean paintText = true;
private boolean paintBackground = false;
@ -42,6 +47,8 @@ public class ProgressIndicator extends JComponent {
private final Arc2D arc = new Arc2D.Double();
private final Ellipse2D circle = new Ellipse2D.Double();
private final Dimension baseSize = new Dimension(32, 32);
public ProgressIndicator() {
this(null);
@ -53,7 +60,7 @@ public class ProgressIndicator extends JComponent {
indeterminate = (model == null);
setFont(new Font(Font.DIALOG, Font.PLAIN, 8));
setFont(new Font(Font.DIALOG, Font.BOLD, 8));
}
@ -69,20 +76,25 @@ public class ProgressIndicator extends JComponent {
@Override
public void paint(Graphics g) {
public void paintComponent(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
double a = Math.min(getWidth(), getHeight());
g2d.scale(a / baseSize.width, a / baseSize.height);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
if (paintBackground) {
frame.setFrame(0, 0, getWidth(), getHeight());
frame.setFrame(0, 0, baseSize.width, baseSize.height);
g2d.setPaint(getBackground());
circle.setFrame(frame);
g2d.fill(circle);
}
frame.setFrame(progressStrokeWidth, progressStrokeWidth, getWidth() - progressStrokeWidth * 2 - 1, getHeight() - progressStrokeWidth * 2 - 1);
double inset = Math.max(Math.max(remainingStrokeWidth, progressStrokeWidth), indeterminateRadius);
frame.setFrame(inset, inset, baseSize.width - inset * 2 - 1, baseSize.height - inset * 2 - 1);
if (!indeterminate) {
paintProgress(g2d);

View File

@ -2,7 +2,6 @@
package net.sourceforge.tuned.ui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.Window;