package net.sf.jabref.gui;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.EventSelectionModel;
import ca.odell.glazedlists.swing.EventTableModel;
import com.jgoodies.forms.builder.ButtonBarBuilder;
import com.jgoodies.forms.builder.ButtonStackBuilder;
import net.sf.jabref.*;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
*
*/
public class FetcherPreviewDialog extends JDialog implements OutputPrinter {
protected EventList<TableEntry> entries = new BasicEventList<TableEntry>();
//protected SortedList<TableEntry> sortedList;
protected JTable glTable;
protected JButton ok = new JButton(Globals.lang("Ok")),
cancel = new JButton(Globals.lang("Cancel"));
protected JButton selectAll = new JButton(Globals.lang("Select all"));
protected JButton deselectAll = new JButton(Globals.lang("Deselect all"));
protected boolean okPressed = false;
private JabRefFrame frame;
private int warningLimit;
public FetcherPreviewDialog(JabRefFrame frame, int warningLimit, int tableRowHeight) {
super(frame, Globals.lang("Title"), true);
this.frame = frame;
this.warningLimit = warningLimit;
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (verifySelection()) {
okPressed = true;
dispose();
}
}
});
cancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
okPressed = false;
dispose();
}
});
selectAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setSelectionAll(true);
}
});
deselectAll.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setSelectionAll(false);
}
});
EventTableModel<TableEntry> tableModelGl = new EventTableModel<TableEntry>(entries,
new EntryTableFormat());
glTable = new EntryTable(tableModelGl);
glTable.setRowHeight(tableRowHeight);
glTable.getColumnModel().getColumn(0).setMaxWidth(45);
glTable.setPreferredScrollableViewportSize(new Dimension(1100, 600));
EventSelectionModel<TableEntry> selectionModel = new EventSelectionModel<TableEntry>(entries);
glTable.setSelectionModel(selectionModel);
ButtonStackBuilder builder = new ButtonStackBuilder();
builder.addButton(selectAll);
builder.addButton(deselectAll);
builder.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
ButtonBarBuilder bb = new ButtonBarBuilder();
bb.addGlue();
bb.addButton(ok);
bb.addButton(cancel);
bb.addGlue();
bb.getPanel().setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
JPanel centerPan = new JPanel();
centerPan.setLayout(new BorderLayout());
centerPan.add(new JScrollPane(glTable), BorderLayout.CENTER);
centerPan.add(builder.getPanel(), BorderLayout.WEST);
getContentPane().add(centerPan, BorderLayout.CENTER);
getContentPane().add(bb.getPanel(), BorderLayout.SOUTH);
// Key bindings:
AbstractAction closeAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
dispose();
}
};
ActionMap am = centerPan.getActionMap();
InputMap im = centerPan.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
im.put(Globals.prefs.getKey("Close dialog"), "close");
am.put("close", closeAction);
pack();
}
/**
* Check whether a large number of entries are selected, and if so, ask the user whether
* to go on.
* @return true if we should go on
*/
public boolean verifySelection() {
int selected = 0;
for (TableEntry entry : entries) {
if (entry.isWanted())
selected++;
}
if (selected > warningLimit) {
int result = JOptionPane.showConfirmDialog(this,
Globals.lang("You have selected more than %0 entries for download. Some web sites "
+"might block you if you make too many rapid downloads. Do you want to continue?",
String.valueOf(warningLimit)),
Globals.lang("Confirm selection"), JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE);
return result == JOptionPane.YES_OPTION;
}
else return true;
}
public Map<String,Boolean> getSelection() {
LinkedHashMap<String, Boolean> selection = new LinkedHashMap<String,Boolean>();
for (TableEntry e : entries)
selection.put(e.id, e.isWanted());
return selection;
}
/* (non-Javadoc)
* @see net.sf.jabref.gui.ImportInspection#addEntry(net.sf.jabref.BibtexEntry)
*/
public void addEntry(String entryId, JLabel preview) {
TableEntry entry = new TableEntry(entryId, preview);
this.entries.getReadWriteLock().writeLock().lock();
this.entries.add(entry);
this.entries.getReadWriteLock().writeLock().unlock();
glTable.repaint();
}
public void setSelectionAll(boolean select) {
for (int i = 0; i < glTable.getRowCount(); i++) {
glTable.setValueAt(select, i, 0);
}
glTable.repaint();
}
class TableEntry {
private String id;
private JLabel preview;
private boolean wanted = false;
public TableEntry(String id, JLabel preview) {
this.id = id;
this.preview = preview;
}
public boolean isWanted() {
return wanted;
}
public void setWanted(boolean wanted) {
this.wanted = wanted;
}
public JLabel getPreview() {
return preview;
}
}
class PreviewRenderer implements TableCellRenderer {
JLabel label = new JLabel();
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
JLabel label = (JLabel)value;
this.label.setText(label.getText());
return this.label;
}
}
class EntryTable extends JTable {
PreviewRenderer renderer = new PreviewRenderer();
public EntryTable(TableModel model) {
super(model);
getTableHeader().setReorderingAllowed(false);
}
public TableCellRenderer getCellRenderer(int row, int column) {
return column == 0 ? getDefaultRenderer(Boolean.class) : renderer;
}
/*
* public TableCellEditor getCellEditor() { return
* getDefaultEditor(Boolean.class); }
*/
public Class<?> getColumnClass(int col) {
if (col == 0)
return Boolean.class;
else
return JLabel.class;
}
public boolean isCellEditable(int row, int column) {
return column == 0;
}
public void setValueAt(Object value, int row, int column) {
// Only column 0, which is controlled by BibtexEntry.searchHit, is
// editable:
entries.getReadWriteLock().writeLock().lock();
TableEntry entry = entries.get(row);
entry.setWanted(((Boolean) value).booleanValue());
entries.getReadWriteLock().writeLock().unlock();
}
}
class EntryTableFormat implements TableFormat<TableEntry> {
public int getColumnCount() {
return 2;
}
public String getColumnName(int i) {
if (i == 0)
return Globals.lang("Keep");
else
return Globals.lang("Preview");
}
public Object getColumnValue(TableEntry entry, int i) {
if (i == 0)
return entry.isWanted() ? Boolean.TRUE : Boolean.FALSE;
else return entry.getPreview();
}
}
public boolean isOkPressed() {
return okPressed;
}
public void setStatus(String s) {
frame.setStatus(s);
}
public void showMessage(Object message, String title, int msgType) {
JOptionPane.showMessageDialog(this, message, title, msgType);
}
public void showMessage(String message) {
JOptionPane.showMessageDialog(this, message);
}
}