* didn't add some files in last commit ...
This commit is contained in:
parent
a547c7e7e9
commit
ffc6a8b931
|
@ -0,0 +1,64 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import static java.awt.BasicStroke.*;
|
||||
import static java.awt.RenderingHints.*;
|
||||
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Insets;
|
||||
|
||||
import javax.swing.border.Border;
|
||||
|
||||
|
||||
class DashedSeparator implements Border {
|
||||
|
||||
private final int height;
|
||||
private final int dash;
|
||||
|
||||
private final Color foreground;
|
||||
private final Color background;
|
||||
|
||||
|
||||
public DashedSeparator(int height, int dash, Color foreground, Color background) {
|
||||
this.height = height;
|
||||
this.dash = dash;
|
||||
this.foreground = foreground;
|
||||
this.background = background;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Insets getBorderInsets(Component c) {
|
||||
return new Insets(0, 0, height, 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBorderOpaque() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) {
|
||||
Graphics2D g2d = (Graphics2D) g.create(x, h - this.height, w, h);
|
||||
|
||||
// fill background
|
||||
g2d.setPaint(background);
|
||||
g2d.fillRect(0, 0, w, h);
|
||||
|
||||
// draw dashed line
|
||||
g2d.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
|
||||
g2d.setColor(foreground);
|
||||
g2d.setStroke(new BasicStroke(1, CAP_ROUND, JOIN_ROUND, 1, new float[] { dash }, 0));
|
||||
|
||||
g2d.drawLine(dash, this.height / 2, w - dash, this.height / 2);
|
||||
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
|
||||
import javax.swing.DefaultListCellRenderer;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
|
||||
import net.sourceforge.filebot.ResourceManager;
|
||||
|
||||
|
||||
class LanguageComboBoxCellRenderer extends DefaultListCellRenderer {
|
||||
|
||||
private final Border padding = new EmptyBorder(2, 2, 2, 2);
|
||||
|
||||
private final Border favoritePadding = new EmptyBorder(0, 6, 0, 6);
|
||||
|
||||
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
Language language = (Language) value;
|
||||
setText(language.getName());
|
||||
setIcon(ResourceManager.getFlagIcon(language.getCode()));
|
||||
|
||||
// default padding
|
||||
setBorder(padding);
|
||||
|
||||
LanguageComboBoxModel model = (LanguageComboBoxModel) list.getModel();
|
||||
|
||||
if ((index > 0 && index <= model.favorites().size())) {
|
||||
// add favorite padding
|
||||
setBorder(new CompoundBorder(favoritePadding, getBorder()));
|
||||
}
|
||||
|
||||
if (index == 0 || index == model.favorites().size()) {
|
||||
// add separator border
|
||||
setBorder(new CompoundBorder(new DashedSeparator(10, 4, Color.lightGray, list.getBackground()), getBorder()));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import static net.sourceforge.filebot.ui.panel.subtitle.Language.*;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.AbstractListModel;
|
||||
import javax.swing.ComboBoxModel;
|
||||
|
||||
|
||||
class LanguageComboBoxModel extends AbstractListModel implements ComboBoxModel {
|
||||
|
||||
public static final Language ALL_LANGUAGES = new Language("undefined", "All Languages");
|
||||
|
||||
private Language selection = ALL_LANGUAGES;
|
||||
|
||||
private List<Language> favorites = new Favorites(2);
|
||||
|
||||
private List<Language> values;
|
||||
|
||||
|
||||
public LanguageComboBoxModel() {
|
||||
values = Arrays.asList(availableLanguages());
|
||||
|
||||
// sort languages by name
|
||||
Collections.sort(values, ALPHABETIC_ORDER);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Language getElementAt(int index) {
|
||||
// "All Languages"
|
||||
if (index == 0) {
|
||||
return ALL_LANGUAGES;
|
||||
}
|
||||
|
||||
// "All Languages" offset
|
||||
index -= 1;
|
||||
|
||||
if (index < favorites.size()) {
|
||||
return favorites.get(index);
|
||||
}
|
||||
|
||||
// "Favorites" offset
|
||||
index -= favorites.size();
|
||||
|
||||
return values.get(index);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
// "All Languages" : favorites[] : values[]
|
||||
return 1 + favorites.size() + values.size();
|
||||
}
|
||||
|
||||
|
||||
public List<Language> favorites() {
|
||||
return favorites;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Language getSelectedItem() {
|
||||
return selection;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setSelectedItem(Object value) {
|
||||
if (value instanceof Language) {
|
||||
selection = (Language) value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected int convertFavoriteIndexToModel(int favoriteIndex) {
|
||||
return 1 + favoriteIndex;
|
||||
}
|
||||
|
||||
|
||||
protected void fireFavoritesAdded(int from, int to) {
|
||||
fireIntervalAdded(this, convertFavoriteIndexToModel(from), convertFavoriteIndexToModel(to));
|
||||
}
|
||||
|
||||
|
||||
protected void fireFavoritesRemoved(int from, int to) {
|
||||
fireIntervalRemoved(this, convertFavoriteIndexToModel(from), convertFavoriteIndexToModel(to));
|
||||
}
|
||||
|
||||
|
||||
private class Favorites extends AbstractList<Language> implements Set<Language> {
|
||||
|
||||
private final List<Language> data;
|
||||
|
||||
private final int capacity;
|
||||
|
||||
|
||||
public Favorites(int capacity) {
|
||||
this.data = new ArrayList<Language>(capacity);
|
||||
this.capacity = capacity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Language get(int index) {
|
||||
return data.get(index);
|
||||
}
|
||||
|
||||
|
||||
public boolean add(Language element) {
|
||||
// add first
|
||||
return addIfAbsent(0, element);
|
||||
}
|
||||
|
||||
|
||||
public void add(int index, Language element) {
|
||||
addIfAbsent(index, element);
|
||||
}
|
||||
|
||||
|
||||
public boolean addIfAbsent(int index, Language element) {
|
||||
// 1. ignore null values
|
||||
// 2. ignore ALL_LANGUAGES
|
||||
// 3. make sure there are no duplicates
|
||||
// 4. limit size to capacity
|
||||
if (element == null || element == ALL_LANGUAGES || contains(element) || index >= capacity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure there is free space
|
||||
if (data.size() >= capacity) {
|
||||
// remove last
|
||||
remove(data.size() - 1);
|
||||
}
|
||||
|
||||
// add clone of language, because KeySelection behaviour will
|
||||
// get weird if the same object is in the model multiple times
|
||||
data.add(index, element.clone());
|
||||
|
||||
// update view
|
||||
fireFavoritesAdded(index, index);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean contains(Object obj) {
|
||||
// check via language code, because data consists of clones
|
||||
if (obj instanceof Language) {
|
||||
Language language = (Language) obj;
|
||||
|
||||
for (Language element : data) {
|
||||
if (language.getCode().equals(element.getCode()))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Language remove(int index) {
|
||||
Language old = data.remove(index);
|
||||
|
||||
// update view
|
||||
fireFavoritesRemoved(index, index);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import static java.awt.event.ItemEvent.*;
|
||||
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
|
||||
|
||||
class PopupSelectionListener implements PopupMenuListener, ItemListener {
|
||||
|
||||
private Object selected = null;
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
|
||||
JComboBox comboBox = (JComboBox) e.getSource();
|
||||
|
||||
// selected item before popup
|
||||
selected = comboBox.getSelectedItem();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
|
||||
JComboBox comboBox = (JComboBox) e.getSource();
|
||||
|
||||
// check selected item after popup
|
||||
if (selected != comboBox.getSelectedItem()) {
|
||||
itemStateChanged(new ItemEvent(comboBox, ITEM_STATE_CHANGED, comboBox.getSelectedItem(), SELECTED));
|
||||
}
|
||||
|
||||
selected = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void popupMenuCanceled(PopupMenuEvent e) {
|
||||
selected = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JProgressBar;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sourceforge.filebot.ResourceManager;
|
||||
import net.sourceforge.tuned.ui.AbstractFancyListCellRenderer;
|
||||
|
||||
|
||||
public class SubtitleListCellRenderer extends AbstractFancyListCellRenderer {
|
||||
|
||||
private final JLabel titleLabel = new JLabel();
|
||||
private final JLabel languageLabel = new JLabel();
|
||||
|
||||
private final JProgressBar progressBar = new JProgressBar(0, 100);
|
||||
|
||||
private final Map<String, String> languageCodeMap = mapLanguageCodeByName(Language.availableLanguages());
|
||||
|
||||
|
||||
public SubtitleListCellRenderer() {
|
||||
setHighlightingEnabled(false);
|
||||
|
||||
progressBar.setStringPainted(true);
|
||||
progressBar.setOpaque(false);
|
||||
progressBar.setPreferredSize(new Dimension(80, 18));
|
||||
|
||||
setLayout(new MigLayout("fill, nogrid, insets 0"));
|
||||
|
||||
add(languageLabel, "hidemode 3, w 85px!");
|
||||
add(titleLabel, "");
|
||||
add(progressBar, "gap indent:push");
|
||||
|
||||
setBorder(new CompoundBorder(new DashedSeparator(2, 4, Color.lightGray, Color.white), getBorder()));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void configureListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
super.configureListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
|
||||
SubtitlePackage subtitle = (SubtitlePackage) value;
|
||||
|
||||
titleLabel.setIcon(ResourceManager.getIcon("status.archive"));
|
||||
titleLabel.setText(subtitle.getName());
|
||||
|
||||
if (languageLabel.isVisible()) {
|
||||
languageLabel.setText(subtitle.getLanguageName());
|
||||
languageLabel.setIcon(ResourceManager.getFlagIcon(languageCodeMap.get(subtitle.getLanguageName())));
|
||||
}
|
||||
|
||||
//TODO download + progress
|
||||
progressBar.setVisible(false);
|
||||
progressBar.setString(subtitle.getDownloadTask().getState().toString().toLowerCase());
|
||||
|
||||
titleLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||
languageLabel.setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
|
||||
|
||||
// don't paint border on last element
|
||||
setBorderPainted(index < list.getModel().getSize() - 1);
|
||||
}
|
||||
|
||||
|
||||
private Map<String, String> mapLanguageCodeByName(Language[] languages) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
|
||||
for (Language language : languages) {
|
||||
map.put(language.getName(), language.getCode());
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
public JLabel getLanguageLabel() {
|
||||
return languageLabel;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void validate() {
|
||||
// validate children, yet avoid flickering of the mouse cursor
|
||||
validateTree();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
package net.sourceforge.filebot.ui.panel.subtitle;
|
||||
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTextField;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sourceforge.filebot.ResourceManager;
|
||||
import ca.odell.glazedlists.BasicEventList;
|
||||
import ca.odell.glazedlists.EventList;
|
||||
import ca.odell.glazedlists.FilterList;
|
||||
import ca.odell.glazedlists.GlazedLists;
|
||||
import ca.odell.glazedlists.ListSelection;
|
||||
import ca.odell.glazedlists.TextFilterator;
|
||||
import ca.odell.glazedlists.swing.EventListModel;
|
||||
import ca.odell.glazedlists.swing.EventSelectionModel;
|
||||
import ca.odell.glazedlists.swing.TextComponentMatcherEditor;
|
||||
|
||||
|
||||
public class SubtitleListComponent extends JComponent {
|
||||
|
||||
private EventList<SubtitlePackage> model = new BasicEventList<SubtitlePackage>();
|
||||
|
||||
private SubtitleListCellRenderer renderer = new SubtitleListCellRenderer();
|
||||
|
||||
private JTextField filterEditor = new JTextField();
|
||||
|
||||
|
||||
public SubtitleListComponent() {
|
||||
TextFilterator<SubtitlePackage> filterator = GlazedLists.toStringTextFilterator();
|
||||
TextComponentMatcherEditor<SubtitlePackage> matcherEditor = new TextComponentMatcherEditor<SubtitlePackage>(filterEditor, filterator);
|
||||
|
||||
JList list = new JList(new EventListModel<SubtitlePackage>(new FilterList<SubtitlePackage>(model, matcherEditor)));
|
||||
list.setCellRenderer(renderer);
|
||||
list.setFixedCellHeight(35);
|
||||
|
||||
EventSelectionModel<SubtitlePackage> selectionModel = new EventSelectionModel<SubtitlePackage>(model);
|
||||
selectionModel.setSelectionMode(ListSelection.MULTIPLE_INTERVAL_SELECTION_DEFENSIVE);
|
||||
list.setSelectionModel(selectionModel);
|
||||
|
||||
JButton clearButton = new JButton(clearFilterAction);
|
||||
clearButton.setOpaque(false);
|
||||
|
||||
setLayout(new MigLayout("fill, nogrid", "[fill]", "[pref!][fill]"));
|
||||
|
||||
add(new JLabel("Filter:"), "gap indent:push");
|
||||
add(filterEditor, "wmin 120px, gap rel");
|
||||
add(clearButton, "w 24px!, h 24px!");
|
||||
add(new JScrollPane(list), "newline");
|
||||
}
|
||||
|
||||
|
||||
public EventList<SubtitlePackage> getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
public void setLanguageVisible(boolean visible) {
|
||||
renderer.getLanguageLabel().setVisible(visible);
|
||||
}
|
||||
|
||||
private final Action clearFilterAction = new AbstractAction(null, ResourceManager.getIcon("edit.clear")) {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
filterEditor.setText("");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<languages>
|
||||
<language code="sq" name="Albanian" />
|
||||
<language code="ar" name="Arabic" />
|
||||
<language code="hy" name="Armenian" />
|
||||
<language code="pb" name="Brazilian" />
|
||||
<language code="bg" name="Bulgarian" />
|
||||
<language code="ca" name="Catalan" />
|
||||
<language code="zh" name="Chinese" />
|
||||
<language code="hr" name="Croatian" />
|
||||
<language code="cs" name="Czech" />
|
||||
<language code="da" name="Danish" />
|
||||
<language code="nl" name="Dutch" />
|
||||
<language code="en" name="English" />
|
||||
<language code="et" name="Estonian" />
|
||||
<language code="fi" name="Finnish" />
|
||||
<language code="fr" name="French" />
|
||||
<language code="de" name="German" />
|
||||
<language code="el" name="Greek" />
|
||||
<language code="he" name="Hebrew" />
|
||||
<language code="hi" name="Hindi" />
|
||||
<language code="hu" name="Hungarian" />
|
||||
<language code="id" name="Indonesian" />
|
||||
<language code="it" name="Italian" />
|
||||
<language code="ja" name="Japanese" />
|
||||
<language code="ko" name="Korean" />
|
||||
<language code="lv" name="Latvian" />
|
||||
<language code="lt" name="Lithuanian" />
|
||||
<language code="mk" name="Macedonian" />
|
||||
<language code="ms" name="Malay" />
|
||||
<language code="no" name="Norwegian" />
|
||||
<language code="fa" name="Persian" />
|
||||
<language code="pl" name="Polish" />
|
||||
<language code="pt" name="Portuguese" />
|
||||
<language code="ro" name="Romanian" />
|
||||
<language code="ru" name="Russian" />
|
||||
<language code="sr" name="Serbian" />
|
||||
<language code="sk" name="Slovak" />
|
||||
<language code="sl" name="Slovenian" />
|
||||
<language code="es" name="Spanish" />
|
||||
<language code="sv" name="Swedish" />
|
||||
<language code="th" name="Thai" />
|
||||
<language code="tr" name="Turkish" />
|
||||
<language code="vi" name="Vietnamese" />
|
||||
</languages>
|
Loading…
Reference in New Issue