mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-23 08:18:52 -05:00
* improved "focus on filter" behaviour in SubtitleViewer
This commit is contained in:
parent
333b362da0
commit
dd736fd4af
@ -5,10 +5,14 @@ package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
import static java.awt.Font.*;
|
||||
import static java.util.Collections.*;
|
||||
import static java.util.regex.Pattern.*;
|
||||
import static net.sourceforge.tuned.ui.TunedUtilities.*;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
@ -28,9 +32,12 @@ import javax.swing.JPanel;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.KeyStroke;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.RowFilter;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.DefaultTableColumnModel;
|
||||
@ -49,15 +56,16 @@ import net.sourceforge.tuned.ui.notification.SeparatorBorder.Position;
|
||||
public class SubtitleViewer extends JFrame {
|
||||
|
||||
private final JLabel titleLabel = new JLabel();
|
||||
|
||||
private final JLabel infoLabel = new JLabel();
|
||||
|
||||
private final SubtitleTableModel model = new SubtitleTableModel();
|
||||
|
||||
private final JTextField filterEditor = new JTextField();
|
||||
|
||||
private final JTable subtitleTable = createTable(model);
|
||||
|
||||
private final JTextField filterEditor = createFilterEditor();
|
||||
|
||||
private Color defaultFilterForeground = filterEditor.getForeground();
|
||||
private Color disabledFilterForeground = Color.lightGray;
|
||||
|
||||
|
||||
public SubtitleViewer(String title) {
|
||||
super(title);
|
||||
@ -87,47 +95,6 @@ public class SubtitleViewer extends JFrame {
|
||||
pane.add(header, "hmin 20px, growx, dock north");
|
||||
pane.add(content, "grow");
|
||||
|
||||
// initialize selection modes
|
||||
subtitleTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
|
||||
final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss", Locale.ROOT);
|
||||
timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
// change time stamp format
|
||||
subtitleTable.setDefaultRenderer(Date.class, new DefaultTableCellRenderer() {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, timeFormat.format(value), isSelected, hasFocus, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
// change text format
|
||||
subtitleTable.setDefaultRenderer(String.class, new DefaultTableCellRenderer() {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, value.toString().replaceAll("\\s+", " "), isSelected, hasFocus, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
// update sequence and element filter on change
|
||||
filterEditor.getDocument().addDocumentListener(new LazyDocumentListener() {
|
||||
|
||||
@Override
|
||||
public void update(DocumentEvent e) {
|
||||
List<SubtitleFilter> filterList = new ArrayList<SubtitleFilter>();
|
||||
|
||||
// filter by all words
|
||||
for (String word : filterEditor.getText().split("\\s+")) {
|
||||
filterList.add(new SubtitleFilter(word));
|
||||
}
|
||||
|
||||
TableRowSorter<?> sorter = (TableRowSorter<?>) subtitleTable.getRowSorter();
|
||||
sorter.setRowFilter(RowFilter.andFilter(filterList));
|
||||
}
|
||||
});
|
||||
|
||||
// initialize window properties
|
||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
||||
setLocationByPlatform(true);
|
||||
@ -136,13 +103,8 @@ public class SubtitleViewer extends JFrame {
|
||||
}
|
||||
|
||||
|
||||
public void setData(List<SubtitleElement> data) {
|
||||
model.setData(data);
|
||||
}
|
||||
|
||||
|
||||
private JTable createTable(TableModel model) {
|
||||
JTable table = new JTable(model);
|
||||
final JTable table = new JTable(model);
|
||||
table.setBackground(Color.white);
|
||||
table.setAutoCreateRowSorter(true);
|
||||
table.setFillsViewportHeight(true);
|
||||
@ -154,10 +116,126 @@ public class SubtitleViewer extends JFrame {
|
||||
m.getColumn(1).setMaxWidth(60);
|
||||
m.getColumn(2).setMaxWidth(60);
|
||||
|
||||
// initialize selection modes
|
||||
table.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
|
||||
final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss", Locale.ROOT);
|
||||
timeFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
|
||||
// change time stamp format
|
||||
table.setDefaultRenderer(Date.class, new DefaultTableCellRenderer() {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, timeFormat.format(value), isSelected, hasFocus, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
// change text format
|
||||
table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() {
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
return super.getTableCellRendererComponent(table, value.toString().replaceAll("\\s+", " "), isSelected, hasFocus, row, column);
|
||||
}
|
||||
});
|
||||
|
||||
// focus around selected time stamp
|
||||
installAction(table, KeyStroke.getKeyStroke("ENTER"), new AbstractAction("focus") {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
// disable row filter
|
||||
setTableFilter(null);
|
||||
|
||||
// ensure selected row is visible and roughly in the center of the table
|
||||
Rectangle focus = table.getCellRect(Math.max(table.getSelectedRow() - 7, 0), 0, true);
|
||||
focus.height = table.getSize().height;
|
||||
table.scrollRectToVisible(focus);
|
||||
}
|
||||
});
|
||||
|
||||
table.addMouseListener(new MouseInputAdapter() {
|
||||
|
||||
@Override
|
||||
public void mouseClicked(MouseEvent e) {
|
||||
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 2) {
|
||||
table.getActionMap().get("focus").actionPerformed(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
|
||||
private JTextField createFilterEditor() {
|
||||
final JTextField editor = new JTextField() {
|
||||
|
||||
@Override
|
||||
protected void processKeyEvent(KeyEvent evt) {
|
||||
int vk = evt.getKeyCode();
|
||||
|
||||
// redirect navigation events to subtitle table
|
||||
if (vk == KeyEvent.VK_UP || vk == KeyEvent.VK_DOWN || vk == KeyEvent.VK_ENTER) {
|
||||
subtitleTable.dispatchEvent(evt);
|
||||
return;
|
||||
}
|
||||
|
||||
// enable filter again
|
||||
if (vk == KeyEvent.VK_BACK_SPACE && !filterEditor.getText().isEmpty() && getTableFilter() == null) {
|
||||
setTableFilter(getText());
|
||||
return;
|
||||
}
|
||||
|
||||
// default key processing
|
||||
super.processKeyEvent(evt);
|
||||
}
|
||||
};
|
||||
|
||||
// update sequence and element filter on change
|
||||
editor.getDocument().addDocumentListener(new LazyDocumentListener(0) {
|
||||
|
||||
@Override
|
||||
public void update(DocumentEvent e) {
|
||||
setTableFilter(editor.getText());
|
||||
}
|
||||
});
|
||||
|
||||
return editor;
|
||||
}
|
||||
|
||||
|
||||
private RowFilter<?, ?> getTableFilter() {
|
||||
TableRowSorter<?> sorter = (TableRowSorter<?>) subtitleTable.getRowSorter();
|
||||
return sorter.getRowFilter();
|
||||
}
|
||||
|
||||
|
||||
private void setTableFilter(String filter) {
|
||||
// filter by words
|
||||
List<SubtitleFilter> filterList = new ArrayList<SubtitleFilter>();
|
||||
|
||||
if (filter != null) {
|
||||
for (String word : filter.split("\\s+")) {
|
||||
if (word.length() > 0) {
|
||||
filterList.add(new SubtitleFilter(word));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TableRowSorter<?> sorter = (TableRowSorter<?>) subtitleTable.getRowSorter();
|
||||
sorter.setRowFilter(filterList.isEmpty() ? null : RowFilter.andFilter(filterList));
|
||||
|
||||
filterEditor.setForeground(filterList.isEmpty() ? disabledFilterForeground : defaultFilterForeground);
|
||||
}
|
||||
|
||||
|
||||
public void setData(List<SubtitleElement> data) {
|
||||
model.setData(data);
|
||||
}
|
||||
|
||||
|
||||
public JLabel getTitleLabel() {
|
||||
return titleLabel;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ public abstract class LazyDocumentListener implements DocumentListener {
|
||||
|
||||
private DocumentEvent lastEvent;
|
||||
|
||||
private final Timer timer;
|
||||
private Timer timer;
|
||||
|
||||
|
||||
public LazyDocumentListener() {
|
||||
@ -23,24 +23,33 @@ public abstract class LazyDocumentListener implements DocumentListener {
|
||||
|
||||
|
||||
public LazyDocumentListener(int delay) {
|
||||
timer = new Timer(delay, new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
update(lastEvent);
|
||||
if (delay >= 0) {
|
||||
timer = new Timer(delay, new ActionListener() {
|
||||
|
||||
// we don't need it anymore
|
||||
lastEvent = null;
|
||||
}
|
||||
});
|
||||
|
||||
timer.setRepeats(false);
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
update(lastEvent);
|
||||
|
||||
// we don't need it anymore
|
||||
lastEvent = null;
|
||||
}
|
||||
});
|
||||
|
||||
timer.setRepeats(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void defer(DocumentEvent e) {
|
||||
public void defer(DocumentEvent e) {
|
||||
lastEvent = e;
|
||||
timer.restart();
|
||||
|
||||
if (timer != null) {
|
||||
// defer update
|
||||
timer.restart();
|
||||
} else {
|
||||
// update immediately
|
||||
update(lastEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user