* added media info button in EpisodeBindingDialog

* improved dialog positioning
* minor bugfixes
* refactoring
This commit is contained in:
Reinhard Pointner 2009-08-02 11:48:45 +00:00
parent f737e7c5fb
commit 3b147b325f
16 changed files with 274 additions and 248 deletions

View File

@ -18,9 +18,8 @@ public class AssociativeScriptObject implements Scriptable {
private final Map<String, Object> properties; private final Map<String, Object> properties;
@SuppressWarnings("unchecked")
public AssociativeScriptObject(Map<String, ?> properties) { public AssociativeScriptObject(Map<String, ?> properties) {
this.properties = new LenientLookup((Map<String, Object>) properties); this.properties = new LenientLookup(properties);
} }
@ -156,15 +155,15 @@ public class AssociativeScriptObject implements Scriptable {
* Map allowing look-up of values by a fault-tolerant key as specified by the defining key. * Map allowing look-up of values by a fault-tolerant key as specified by the defining key.
* *
*/ */
private class LenientLookup extends AbstractMap<String, Object> { private static class LenientLookup extends AbstractMap<String, Object> {
private final Map<String, Entry<String, Object>> source = new HashMap<String, Entry<String, Object>>(); private final Map<String, Entry<String, ?>> lookup = new HashMap<String, Entry<String, ?>>();
public LenientLookup(Map<String, Object> source) { public LenientLookup(Map<String, ?> source) {
// populate entry map // populate lookup map
for (Entry<String, Object> entry : source.entrySet()) { for (Entry<String, ?> entry : source.entrySet()) {
this.source.put(definingKey(entry.getKey()), entry); lookup.put(definingKey(entry.getKey()), entry);
} }
} }
@ -177,13 +176,13 @@ public class AssociativeScriptObject implements Scriptable {
@Override @Override
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
return source.containsKey(definingKey(key)); return lookup.containsKey(definingKey(key));
} }
@Override @Override
public Object get(Object key) { public Object get(Object key) {
Entry<String, Object> entry = source.get(definingKey(key)); Entry<String, ?> entry = lookup.get(definingKey(key));
if (entry != null) if (entry != null)
return entry.getValue(); return entry.getValue();
@ -198,13 +197,15 @@ public class AssociativeScriptObject implements Scriptable {
@Override @Override
public Iterator<Entry<String, Object>> iterator() { public Iterator<Entry<String, Object>> iterator() {
return source.values().iterator(); @SuppressWarnings("unchecked")
Iterator<Entry<String, Object>> iterator = (Iterator) lookup.values().iterator();
return iterator;
} }
@Override @Override
public int size() { public int size() {
return source.size(); return lookup.size();
} }
}; };
} }

View File

@ -211,11 +211,11 @@ public class EpisodeBindingBean {
private void checkMediaFile() throws RuntimeException { private void checkMediaFile() throws RuntimeException {
// make sure file is not null, and that it is an existing file // make sure file is not null, and that it is an existing file
if (mediaFile == null || !mediaFile.isFile()) if (mediaFile == null || !mediaFile.isFile())
throw new RuntimeException(String.format("Illegal media file: %s", mediaFile)); throw new RuntimeException(String.format("Invalid media file: %s", mediaFile));
} }
private MediaInfo getMediaInfo() { private synchronized MediaInfo getMediaInfo() {
if (mediaInfo == null) { if (mediaInfo == null) {
// make sure media file is defined // make sure media file is defined
checkMediaFile(); checkMediaFile();

View File

@ -41,7 +41,7 @@ public class MediaInfo implements Closeable {
public synchronized boolean open(File file) { public synchronized boolean open(File file) {
return MediaInfoLibrary.INSTANCE.Open(handle, new WString(file.getAbsolutePath())) > 0; return file.isFile() && MediaInfoLibrary.INSTANCE.Open(handle, new WString(file.getAbsolutePath())) > 0;
} }

View File

@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui;
import static javax.swing.ScrollPaneConstants.*; import static javax.swing.ScrollPaneConstants.*;
import static net.sourceforge.tuned.ui.TunedUtilities.*;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -40,7 +41,6 @@ import net.sourceforge.filebot.web.SearchResult;
import net.sourceforge.tuned.ExceptionUtilities; import net.sourceforge.tuned.ExceptionUtilities;
import net.sourceforge.tuned.ListChangeSynchronizer; import net.sourceforge.tuned.ListChangeSynchronizer;
import net.sourceforge.tuned.ui.LabelProvider; import net.sourceforge.tuned.ui.LabelProvider;
import net.sourceforge.tuned.ui.TunedUtilities;
public abstract class AbstractSearchPanel<S, E> extends JComponent { public abstract class AbstractSearchPanel<S, E> extends JComponent {
@ -97,7 +97,7 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory).setFilterMode(TextMatcherEditor.CONTAINS); AutoCompleteSupport.install(searchTextField.getEditor(), searchHistory).setFilterMode(TextMatcherEditor.CONTAINS);
TunedUtilities.installAction(this, KeyStroke.getKeyStroke("ENTER"), searchAction); installAction(this, KeyStroke.getKeyStroke("ENTER"), searchAction);
} }
@ -383,7 +383,6 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
protected SearchResult selectSearchResult(Collection<? extends SearchResult> searchResults, Window window) throws Exception { protected SearchResult selectSearchResult(Collection<? extends SearchResult> searchResults, Window window) throws Exception {
// multiple results have been found, user must select one // multiple results have been found, user must select one
SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(window, searchResults); SelectDialog<SearchResult> selectDialog = new SelectDialog<SearchResult>(window, searchResults);
configureSelectDialog(selectDialog); configureSelectDialog(selectDialog);
selectDialog.setVisible(true); selectDialog.setVisible(true);
@ -394,7 +393,8 @@ public abstract class AbstractSearchPanel<S, E> extends JComponent {
protected void configureSelectDialog(SelectDialog<SearchResult> selectDialog) { protected void configureSelectDialog(SelectDialog<SearchResult> selectDialog) {
selectDialog.setIconImage(TunedUtilities.getImage(getIcon())); selectDialog.setLocation(getOffsetLocation(selectDialog.getOwner()));
selectDialog.setIconImage(getImage(getIcon()));
} }

View File

@ -2,6 +2,7 @@
package net.sourceforge.filebot.ui; package net.sourceforge.filebot.ui;
import java.awt.Component;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -48,7 +49,14 @@ public class SelectDialog<T> extends JDialog {
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
list.setSelectedIndex(0); list.setSelectedIndex(0);
DefaultFancyListCellRenderer renderer = new DefaultFancyListCellRenderer(4); DefaultFancyListCellRenderer renderer = new DefaultFancyListCellRenderer(4) {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
return super.getListCellRendererComponent(list, convertValueToString(value), index, isSelected, cellHasFocus);
}
};
renderer.setHighlightingEnabled(false); renderer.setHighlightingEnabled(false);
list.setCellRenderer(renderer); list.setCellRenderer(renderer);
@ -66,7 +74,6 @@ public class SelectDialog<T> extends JDialog {
// set default size and location // set default size and location
setSize(new Dimension(210, 210)); setSize(new Dimension(210, 210));
setLocation(TunedUtilities.getPreferredLocation(this));
// Shortcut Enter // Shortcut Enter
TunedUtilities.installAction(list, KeyStroke.getKeyStroke("released ENTER"), selectAction); TunedUtilities.installAction(list, KeyStroke.getKeyStroke("released ENTER"), selectAction);

View File

@ -3,6 +3,7 @@ package net.sourceforge.filebot.ui.panel.rename;
import static net.sourceforge.filebot.FileBotUtilities.*; import static net.sourceforge.filebot.FileBotUtilities.*;
import static net.sourceforge.tuned.ui.TunedUtilities.*;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
@ -109,6 +110,7 @@ class AutoFetchEpisodeListMatcher extends SwingWorker<List<Match<File, Episode>>
selectDialog.getCancelAction().putValue(Action.NAME, "Ignore"); selectDialog.getCancelAction().putValue(Action.NAME, "Ignore");
// show dialog // show dialog
selectDialog.setLocation(getOffsetLocation(selectDialog.getOwner()));
selectDialog.setVisible(true); selectDialog.setVisible(true);
// selected value or null if the dialog was canceled by the user // selected value or null if the dialog was canceled by the user

View File

@ -14,8 +14,10 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.ResourceBundle; import java.util.ResourceBundle;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
@ -38,6 +40,7 @@ import javax.swing.JScrollPane;
import javax.swing.JTabbedPane; import javax.swing.JTabbedPane;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener; import javax.swing.event.DocumentListener;
@ -45,12 +48,15 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel; import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import net.miginfocom.swing.MigLayout; import net.miginfocom.swing.MigLayout;
import net.sourceforge.filebot.MediaTypes; import net.sourceforge.filebot.MediaTypes;
import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ResourceManager;
import net.sourceforge.filebot.format.EpisodeBindingBean; import net.sourceforge.filebot.format.EpisodeBindingBean;
import net.sourceforge.filebot.format.ExpressionFormat; import net.sourceforge.filebot.format.ExpressionFormat;
import net.sourceforge.filebot.mediainfo.MediaInfo;
import net.sourceforge.filebot.mediainfo.MediaInfo.StreamKind;
import net.sourceforge.filebot.web.Episode; import net.sourceforge.filebot.web.Episode;
import net.sourceforge.filebot.web.EpisodeFormat; import net.sourceforge.filebot.web.EpisodeFormat;
import net.sourceforge.tuned.DefaultThreadFactory; import net.sourceforge.tuned.DefaultThreadFactory;
@ -76,11 +82,6 @@ class EpisodeBindingDialog extends JDialog {
public EpisodeBindingDialog(Window owner) { public EpisodeBindingDialog(Window owner) {
super(owner, "Episode Bindings", ModalityType.DOCUMENT_MODAL); super(owner, "Episode Bindings", ModalityType.DOCUMENT_MODAL);
// create image button from action
JButton selectFileButton = new JButton(selectFileAction);
selectFileButton.setHideActionText(true);
selectFileButton.setOpaque(false);
JComponent root = (JComponent) getContentPane(); JComponent root = (JComponent) getContentPane();
root.setLayout(new MigLayout("nogrid, fill, insets dialog")); root.setLayout(new MigLayout("nogrid, fill, insets dialog"));
@ -96,7 +97,8 @@ class EpisodeBindingDialog extends JDialog {
inputPanel.add(new JLabel("Media File:"), "wrap 2px"); inputPanel.add(new JLabel("Media File:"), "wrap 2px");
inputPanel.add(mediaFileTextField, "hmin 20px, growx"); inputPanel.add(mediaFileTextField, "hmin 20px, growx");
inputPanel.add(selectFileButton, "gap rel, w 26px!, h 24px!, wrap paragraph"); inputPanel.add(createImageButton(mediaInfoAction), "gap rel, w 26px!, h 24px!");
inputPanel.add(createImageButton(selectFileAction), "gap rel, w 26px!, h 24px!, wrap paragraph");
inputContainer.add("Episode Bindings", inputPanel); inputContainer.add("Episode Bindings", inputPanel);
root.add(inputContainer, "growx, wrap paragraph"); root.add(inputContainer, "growx, wrap paragraph");
@ -120,9 +122,34 @@ class EpisodeBindingDialog extends JDialog {
} }
}; };
// update example bindings on change
episodeTextField.getDocument().addDocumentListener(changeListener); episodeTextField.getDocument().addDocumentListener(changeListener);
mediaFileTextField.getDocument().addDocumentListener(changeListener); mediaFileTextField.getDocument().addDocumentListener(changeListener);
// disabled by default
mediaInfoAction.setEnabled(false);
// disable media info action if media file is invalid
mediaFileTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
mediaInfoAction.setEnabled(getMediaFile() != null && getMediaFile().isFile());
}
@Override
public void removeUpdate(DocumentEvent e) {
changedUpdate(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
changedUpdate(e);
}
});
// finish dialog and close window manually // finish dialog and close window manually
addWindowListener(new WindowAdapter() { addWindowListener(new WindowAdapter() {
@ -134,15 +161,22 @@ class EpisodeBindingDialog extends JDialog {
// initialize window properties // initialize window properties
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setLocation(getPreferredLocation(this));
setSize(420, 520); setSize(420, 520);
} }
private JButton createImageButton(Action action) {
JButton button = new JButton(action);
button.setHideActionText(true);
button.setOpaque(false);
return button;
}
private JTable createBindingTable(TableModel model) { private JTable createBindingTable(TableModel model) {
JTable table = new JTable(model); JTable table = new JTable(model);
table.setAutoCreateRowSorter(true); table.setAutoCreateRowSorter(true);
table.setFillsViewportHeight(true); table.setFillsViewportHeight(true);
table.setBackground(Color.white); table.setBackground(Color.white);
@ -270,6 +304,87 @@ class EpisodeBindingDialog extends JDialog {
} }
}; };
protected final Action mediaInfoAction = new AbstractAction("Info", ResourceManager.getIcon("action.properties")) {
private Map<StreamKind, List<Map<String, String>>> getMediaInfo(File file) {
try {
MediaInfo mediaInfo = new MediaInfo();
// read all media info
if (mediaInfo.open(file)) {
try {
return mediaInfo.snapshot();
} finally {
mediaInfo.close();
}
}
} catch (LinkageError e) {
Logger.getLogger("ui").log(Level.SEVERE, "Unable to load native library 'mediainfo'", e);
}
// could not retrieve media info
return null;
}
@Override
public void actionPerformed(ActionEvent evt) {
Map<StreamKind, List<Map<String, String>>> mediaInfo = getMediaInfo(getMediaFile());
// check if we could get some info
if (mediaInfo == null)
return;
// create table tab for each stream
JTabbedPane tabbedPane = new JTabbedPane();
ResourceBundle bundle = ResourceBundle.getBundle(EpisodeBindingDialog.class.getName());
RowFilter<Object, Object> excludeRowFilter = RowFilter.notFilter(RowFilter.regexFilter(bundle.getString("parameter.exclude")));
for (StreamKind streamKind : mediaInfo.keySet()) {
for (Map<String, String> parameters : mediaInfo.get(streamKind)) {
JPanel panel = new JPanel(new MigLayout("fill"));
panel.setOpaque(false);
JTable table = new JTable(new ParameterTableModel(parameters));
table.setAutoCreateRowSorter(true);
table.setFillsViewportHeight(true);
table.setBackground(Color.white);
// set media info exclude filter
TableRowSorter<?> sorter = (TableRowSorter<?>) table.getRowSorter();
sorter.setRowFilter(excludeRowFilter);
panel.add(new JScrollPane(table), "grow");
tabbedPane.addTab(streamKind.toString(), panel);
}
}
// show media info dialog
final JDialog dialog = new JDialog(getWindow(evt.getSource()), "MediaInfo", ModalityType.DOCUMENT_MODAL);
Action closeAction = new AbstractAction("OK") {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
dialog.dispose();
}
};
JComponent c = (JComponent) dialog.getContentPane();
c.setLayout(new MigLayout("fill", "[align center]", "[fill][pref!]"));
c.add(tabbedPane, "grow, wrap");
c.add(new JButton(closeAction), "wmin 80px, hmin 25px");
dialog.pack();
dialog.setLocationRelativeTo(EpisodeBindingDialog.this);
dialog.setVisible(true);
}
};
protected final Action selectFileAction = new AbstractAction("Select File", ResourceManager.getIcon("action.load")) { protected final Action selectFileAction = new AbstractAction("Select File", ResourceManager.getIcon("action.load")) {
@Override @Override
@ -287,24 +402,55 @@ class EpisodeBindingDialog extends JDialog {
chooser.setMultiSelectionEnabled(false); chooser.setMultiSelectionEnabled(false);
if (chooser.showOpenDialog(getWindow(evt.getSource())) == JFileChooser.APPROVE_OPTION) { if (chooser.showOpenDialog(getWindow(evt.getSource())) == JFileChooser.APPROVE_OPTION) {
File selectedFile = chooser.getSelectedFile();
if (selectedFile.isFile()) {
try {
// display media info
MediaInfoPane.showMessageDialog(getWindow(evt.getSource()), selectedFile);
} catch (LinkageError e) {
Logger.getLogger("ui").log(Level.SEVERE, "Unable to load native library 'mediainfo'", e);
}
// update text field // update text field
mediaFileTextField.setText(selectedFile.getAbsolutePath()); mediaFileTextField.setText(chooser.getSelectedFile().getAbsolutePath());
}
} }
} }
}; };
private static class Evaluator extends SwingWorker<String, Void> {
private final String expression;
private final Object bindingBean;
private Evaluator(String expression, Object bindingBean) {
this.expression = expression;
this.bindingBean = bindingBean;
}
public String getExpression() {
return expression;
}
@Override
protected String doInBackground() throws Exception {
ExpressionFormat format = new ExpressionFormat(expression) {
@Override
protected Object[] compile(String expression, Compilable engine) throws ScriptException {
// simple expression format, everything as one expression
return new Object[] { engine.compile(expression) };
}
};
// evaluate expression with given bindings
String value = format.format(bindingBean);
// check for script exceptions
if (format.caughtScriptException() != null) {
throw format.caughtScriptException();
}
return value;
}
}
private static class BindingTableModel extends AbstractTableModel { private static class BindingTableModel extends AbstractTableModel {
private final List<Evaluator> model = new ArrayList<Evaluator>(); private final List<Evaluator> model = new ArrayList<Evaluator>();
@ -410,45 +556,52 @@ class EpisodeBindingDialog extends JDialog {
} }
private static class Evaluator extends SwingWorker<String, Void> { private static class ParameterTableModel extends AbstractTableModel {
private final String expression; private final List<Entry<?, ?>> data;
private final Object bindingBean;
private Evaluator(String expression, Object bindingBean) { public ParameterTableModel(Map<?, ?> data) {
this.expression = expression; this.data = new ArrayList<Entry<?, ?>>(data.entrySet());
this.bindingBean = bindingBean;
}
public String getExpression() {
return expression;
} }
@Override @Override
protected String doInBackground() throws Exception { public int getRowCount() {
ExpressionFormat format = new ExpressionFormat(expression) { return data.size();
}
@Override @Override
protected Object[] compile(String expression, Compilable engine) throws ScriptException { public int getColumnCount() {
// simple expression format, everything as one expression return 2;
return new Object[] { engine.compile(expression) };
}
};
// evaluate expression with given bindings
String value = format.format(bindingBean);
// check for script exceptions
if (format.caughtScriptException() != null) {
throw format.caughtScriptException();
}
return value;
} }
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "Parameter";
case 1:
return "Value";
default:
return null;
}
}
@Override
public Object getValueAt(int row, int column) {
switch (column) {
case 0:
return data.get(row).getKey();
case 1:
return data.get(row).getValue();
default:
return null;
}
}
} }
} }

View File

@ -1,4 +1,7 @@
# expressions are tagged so they can be sorted alphabetically # exclude pattern for media info dialog
parameter.exclude: ^StreamKind|Count$
# preview expressions (keys are tagged so they can be sorted alphabetically)
# episode expressions # episode expressions
expr[a1]: n expr[a1]: n
@ -22,22 +25,22 @@ expr[c4]: crc32
# media info expressions [media] # media info expressions [media]
expr[d1]: media.title expr[d1]: media.title
expr[d2]: media.DurationString expr[d2]: media.durationString
expr[d3]: media.OverallBitRateString expr[d3]: media.overallBitRateString
# media info expressions [video] # media info expressions [video]
expr[e1]: video.Codec expr[e1]: video.codec
expr[e2]: video.FrameRate expr[e2]: video.frameRate
expr[e3]: video.DisplayAspectRatioString expr[e3]: video.displayAspectRatioString
expr[e4]: video.Height expr[e4]: video.height
expr[e5]: video.InterlacementString expr[e5]: video.interlacementString
# media info expressions [audio] # media info expressions [audio]
expr[f1]: audio.Codec expr[f1]: audio.codec
expr[f2]: audio.Channels expr[f2]: audio.channels
expr[f3]: audio.BitRateString expr[f3]: audio.bitRateString
expr[f4]: audio.Language expr[f4]: audio.language
# media info expressions [text] # media info expressions [text]
expr[g1]: text.CodecInfo expr[g1]: text.codecInfo
expr[g2]: text.Language expr[g2]: text.language

View File

@ -7,6 +7,7 @@ import static javax.swing.BorderFactory.*;
import static net.sourceforge.tuned.ui.TunedUtilities.*; import static net.sourceforge.tuned.ui.TunedUtilities.*;
import java.awt.Color; import java.awt.Color;
import java.awt.Component;
import java.awt.Font; import java.awt.Font;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -194,7 +195,6 @@ class EpisodeFormatDialog extends JDialog {
// initialize window properties // initialize window properties
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
setLocation(getPreferredLocation(this));
pack(); pack();
} }
@ -423,6 +423,7 @@ class EpisodeFormatDialog extends JDialog {
dialog.setMediaFile(sample.getMediaFile()); dialog.setMediaFile(sample.getMediaFile());
// open dialog // open dialog
dialog.setLocationRelativeTo((Component) evt.getSource());
dialog.setVisible(true); dialog.setVisible(true);
if (dialog.getSelectedOption() == EpisodeBindingDialog.Option.APPROVE) { if (dialog.getSelectedOption() == EpisodeBindingDialog.Option.APPROVE) {

View File

@ -2,6 +2,8 @@
package net.sourceforge.filebot.ui.panel.rename; package net.sourceforge.filebot.ui.panel.rename;
import static net.sourceforge.tuned.ui.TunedUtilities.*;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Window; import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
@ -15,8 +17,6 @@ import java.util.logging.Logger;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import net.sourceforge.filebot.ResourceManager; import net.sourceforge.filebot.ResourceManager;
@ -46,9 +46,8 @@ class MatchAction extends AbstractAction {
if (model.names().isEmpty() || model.files().isEmpty()) if (model.names().isEmpty() || model.files().isEmpty())
return; return;
JComponent eventSource = (JComponent) evt.getSource(); Window window = getWindow(evt.getSource());
window.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
SwingUtilities.getRoot(eventSource).setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
BackgroundMatcher backgroundMatcher = new BackgroundMatcher(model, MatchSimilarityMetric.defaultSequence()); BackgroundMatcher backgroundMatcher = new BackgroundMatcher(model, MatchSimilarityMetric.defaultSequence());
backgroundMatcher.execute(); backgroundMatcher.execute();
@ -58,15 +57,16 @@ class MatchAction extends AbstractAction {
backgroundMatcher.get(2, TimeUnit.SECONDS); backgroundMatcher.get(2, TimeUnit.SECONDS);
} catch (TimeoutException ex) { } catch (TimeoutException ex) {
// matcher will probably take a while // matcher will probably take a while
ProgressDialog progressDialog = createProgressDialog(SwingUtilities.getWindowAncestor(eventSource), backgroundMatcher); ProgressDialog dialog = createProgressDialog(window, backgroundMatcher);
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
// display progress dialog and stop blocking EDT // display progress dialog and stop blocking EDT
progressDialog.setVisible(true); dialog.setVisible(true);
} catch (Exception e) { } catch (Exception e) {
Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.toString(), e); Logger.getLogger(getClass().getName()).log(Level.SEVERE, e.toString(), e);
} }
SwingUtilities.getRoot(eventSource).setCursor(Cursor.getDefaultCursor()); window.setCursor(Cursor.getDefaultCursor());
} }

View File

@ -1,136 +0,0 @@
package net.sourceforge.filebot.ui.panel.rename;
import static net.sourceforge.tuned.ui.TunedUtilities.*;
import java.awt.Window;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import net.miginfocom.swing.MigLayout;
import net.sourceforge.filebot.mediainfo.MediaInfo;
import net.sourceforge.filebot.mediainfo.MediaInfo.StreamKind;
class MediaInfoPane extends JTabbedPane {
public MediaInfoPane(File file) {
// get media info
MediaInfo mediaInfo = new MediaInfo();
if (!mediaInfo.open(file))
throw new IllegalArgumentException("Cannot open file: " + file);
// create tab for each stream
for (Entry<StreamKind, List<Map<String, String>>> entry : mediaInfo.snapshot().entrySet()) {
for (Map<String, String> parameters : entry.getValue()) {
addTableTab(entry.getKey().toString(), parameters);
}
}
mediaInfo.close();
}
public void addTableTab(String title, Map<String, String> data) {
JTable table = new JTable(new ParameterTableModel(data));
table.setFillsViewportHeight(true);
// allow sorting
table.setAutoCreateRowSorter(true);
// sort by parameter name
table.getRowSorter().toggleSortOrder(0);
addTab(title, new JScrollPane(table));
}
public static void showMessageDialog(Window parent, File file) {
final JDialog dialog = new JDialog(parent, "MediaInfo", ModalityType.DOCUMENT_MODAL);
Action closeAction = new AbstractAction("OK") {
@Override
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
dialog.dispose();
}
};
JComponent c = (JComponent) dialog.getContentPane();
c.setLayout(new MigLayout("fill", "[align center]", "[fill][pref!]"));
c.add(new MediaInfoPane(file), "grow, wrap");
c.add(new JButton(closeAction), "wmin 80px, hmin 25px");
dialog.setLocation(getPreferredLocation(dialog));
dialog.pack();
dialog.setVisible(true);
}
private static class ParameterTableModel extends AbstractTableModel {
private final List<Entry<String, String>> data;
public ParameterTableModel(Map<String, String> data) {
this.data = new ArrayList<Entry<String, String>>(data.entrySet());
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "Parameter";
case 1:
return "Value";
}
return null;
}
@Override
public Object getValueAt(int row, int column) {
switch (column) {
case 0:
return data.get(row).getKey();
case 1:
return data.get(row).getValue();
}
return null;
}
}
}

View File

@ -152,7 +152,7 @@ public class RenamePanel extends JComponent {
@Override @Override
public void actionPerformed(ActionEvent evt) { public void actionPerformed(ActionEvent evt) {
EpisodeFormatDialog dialog = new EpisodeFormatDialog(SwingUtilities.getWindowAncestor(RenamePanel.this)); EpisodeFormatDialog dialog = new EpisodeFormatDialog(SwingUtilities.getWindowAncestor(RenamePanel.this));
dialog.setLocation(getOffsetLocation(dialog.getOwner()));
dialog.setVisible(true); dialog.setVisible(true);
switch (dialog.getSelectedOption()) { switch (dialog.getSelectedOption()) {
@ -191,6 +191,7 @@ public class RenamePanel extends JComponent {
History model = HistorySpooler.getInstance().getCompleteHistory(); History model = HistorySpooler.getInstance().getCompleteHistory();
HistoryDialog dialog = new HistoryDialog(getWindow(RenamePanel.this)); HistoryDialog dialog = new HistoryDialog(getWindow(RenamePanel.this));
dialog.setLocationRelativeTo(RenamePanel.this);
dialog.setModel(model); dialog.setModel(model);
// show and block // show and block

View File

@ -50,7 +50,6 @@ public class SfvPanel extends JComponent {
public SfvPanel() { public SfvPanel() {
table.setTransferHandler(new DefaultTransferHandler(transferablePolicy, exportHandler)); table.setTransferHandler(new DefaultTransferHandler(transferablePolicy, exportHandler));
JPanel contentPane = new JPanel(new MigLayout("insets 0, nogrid, fill", "", "[fill]10px[bottom, pref!]4px")); JPanel contentPane = new JPanel(new MigLayout("insets 0, nogrid, fill", "", "[fill]10px[bottom, pref!]4px"));
@ -128,6 +127,7 @@ public class SfvPanel extends JComponent {
} }
} }
private final SaveAction saveAction = new ChecksumTableSaveAction(); private final SaveAction saveAction = new ChecksumTableSaveAction();
private final LoadAction loadAction = new LoadAction(transferablePolicy); private final LoadAction loadAction = new LoadAction(transferablePolicy);
@ -282,6 +282,7 @@ public class SfvPanel extends JComponent {
}; };
selectDialog.getHeaderLabel().setText("Select checksum column:"); selectDialog.getHeaderLabel().setText("Select checksum column:");
selectDialog.setLocationRelativeTo(SfvPanel.this);
selectDialog.setVisible(true); selectDialog.setVisible(true);
this.selectedColumn = selectDialog.getSelectedValue(); this.selectedColumn = selectDialog.getSelectedValue();

View File

@ -110,10 +110,8 @@ public abstract class AbstractFancyListCellRenderer extends JPanel implements Li
@Override @Override
public final Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus); configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
validate(); validate();
return this; return this;

View File

@ -39,7 +39,6 @@ public class ProgressDialog extends JDialog {
progressBar.setStringPainted(true); progressBar.setStringPainted(true);
JPanel c = (JPanel) getContentPane(); JPanel c = (JPanel) getContentPane();
c.setLayout(new MigLayout("insets dialog, nogrid, fill")); c.setLayout(new MigLayout("insets dialog, nogrid, fill"));
c.add(iconLabel, "h pref!, w pref!"); c.add(iconLabel, "h pref!, w pref!");
@ -49,8 +48,6 @@ public class ProgressDialog extends JDialog {
c.add(new JButton(cancelAction), "align center"); c.add(new JButton(cancelAction), "align center");
setSize(240, 155); setSize(240, 155);
setLocation(TunedUtilities.getPreferredLocation(this));
} }
@ -81,6 +78,7 @@ public class ProgressDialog extends JDialog {
dispose(); dispose();
} }
protected final Action cancelAction = new AbstractAction("Cancel") { protected final Action cancelAction = new AbstractAction("Cancel") {
@Override @Override

View File

@ -20,7 +20,6 @@ import javax.swing.Action;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.ImageIcon; import javax.swing.ImageIcon;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.KeyStroke; import javax.swing.KeyStroke;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -100,9 +99,7 @@ public final class TunedUtilities {
} }
public static Point getPreferredLocation(JDialog dialog) { public static Point getOffsetLocation(Window owner) {
Window owner = dialog.getOwner();
if (owner == null) { if (owner == null) {
Window[] toplevel = Window.getOwnerlessWindows(); Window[] toplevel = Window.getOwnerlessWindows();