package org.limewire.ui.swing.properties;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventObject;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.border.Border;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXTable;
import org.limewire.core.api.library.LocalFileItem;
import org.limewire.core.api.library.PropertiableFile;
import org.limewire.core.api.library.SharedFileList;
import org.limewire.core.api.library.SharedFileListManager;
import org.limewire.ui.swing.components.YesNoCheckBoxDialog;
import org.limewire.ui.swing.library.table.RemoveButton;
import org.limewire.ui.swing.properties.FileInfoDialog.FileInfoType;
import org.limewire.ui.swing.settings.QuestionsHandler;
import org.limewire.ui.swing.table.MouseableTable;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
import ca.odell.glazedlists.BasicEventList;
import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.gui.TableFormat;
import ca.odell.glazedlists.swing.DefaultEventTableModel;
public class FileInfoSharingPanel implements FileInfoPanel {
@Resource private Color foreground;
@Resource private Font headerFont;
@Resource private Icon publicIcon;
@Resource private Icon listSharedIcon;
private final JPanel component;
private final FileInfoType type;
private final PropertiableFile propertiableFile;
private final SharedFileListManager sharedFileListManager;
public FileInfoSharingPanel(FileInfoType type, PropertiableFile propertiableFile,
SharedFileListManager sharedFileListManager) {
this.type = type;
this.propertiableFile = propertiableFile;
this.sharedFileListManager = sharedFileListManager;
GuiUtils.assignResources(this);
component = new JPanel(new MigLayout("fillx"));
init();
}
public JComponent getComponent() {
return component;
}
@Override
public boolean hasChanged() {
return false;
}
@Override
public void save() {
//currently the lists are updated on click, not on save
}
@Override
public void dispose() {
//no listeners registered
}
@Override
public void updatePropertiableFile(PropertiableFile file) {
//do nothing
}
private void init() {
component.setOpaque(false);
switch(type) {
case LOCAL_FILE:
if(propertiableFile instanceof LocalFileItem) {
if(((LocalFileItem)propertiableFile).isShareable()) {
EventList<SharedFileList> sharedWithList = getSharedWithList((LocalFileItem)propertiableFile);
if(sharedWithList.size() > 0) {
component.add(createHeaderLabel(I18n.tr("Sharing from these lists")), "span, wrap");
JXTable table = new MouseableTable(new DefaultEventTableModel<SharedFileList>(sharedWithList,
new TableFormat<SharedFileList>() {
@Override
public int getColumnCount() {
return 3;
}
@Override
public String getColumnName(int column) {
return null;
}
@Override
public Object getColumnValue(SharedFileList baseObject, int column) {
switch (column) {
case 0 :
return baseObject.isPublic() ? publicIcon : listSharedIcon;
case 2 :
return baseObject;
default :
return baseObject.getCollectionName();
}
}
}
));
table.setShowGrid(false, false);
table.setTableHeader(null);
table.getColumn(0).setCellRenderer(new IconRenderer());
table.getColumn(0).setMinWidth(26);
table.getColumn(0).setMaxWidth(26);
table.getColumn(0).setWidth(26);
JScrollPane scroll = new JScrollPane(table);
scroll.setOpaque(false);
scroll.setBorder(BorderFactory.createLineBorder(Color.BLACK));
TableColumn column = table.getColumn(2);
column.setCellRenderer(new RemoveRenderer());
column.setCellEditor(new RemoveEditor());
column.setMinWidth(16);
column.setMaxWidth(16);
column.setWidth(16);
component.add(scroll, "grow, wrap");
} else {
component.add(createHeaderLabel(I18n.tr("This file is not shared")), "span, wrap");
}
} else {
component.add(createHeaderLabel(I18n.tr("This file cannot be shared")), "span, wrap");
}
}
break;
}
}
/**
* Returns list of file lists that are shared and contain this file.
*/
private EventList<SharedFileList> getSharedWithList(LocalFileItem fileItem) {
EventList<SharedFileList> sharedWith = new BasicEventList<SharedFileList>();
sharedFileListManager.getModel().getReadWriteLock().readLock().lock();
try {
for(SharedFileList sharedFileList : sharedFileListManager.getModel()) {
if(sharedFileList.contains(fileItem.getFile()) && sharedFileList.getFriendIds().size() > 0)
sharedWith.add(sharedFileList);
}
} finally {
sharedFileListManager.getModel().getReadWriteLock().readLock().unlock();
}
return sharedWith;
}
private JLabel createHeaderLabel(String text) {
JLabel label = new JLabel(text);
label.setFont(headerFont);
label.setForeground(foreground);
return label;
}
private boolean showConfirmation(String message) {
if (!QuestionsHandler.CONFIRM_REMOVE_FILE_INFO_SHARING.getValue()) {
// no need to confirm here
return true;
}
final YesNoCheckBoxDialog yesNoCheckBoxDialog = new YesNoCheckBoxDialog(I18n.tr("Remove File"), message, I18n
.tr("Don't ask me again"), !QuestionsHandler.CONFIRM_REMOVE_FILE_INFO_SHARING.getValue(),
I18n.tr("Yes"), I18n.tr("No"));
yesNoCheckBoxDialog.setLocationRelativeTo(GuiUtils.getMainFrame());
yesNoCheckBoxDialog.setVisible(true);
QuestionsHandler.CONFIRM_REMOVE_FILE_INFO_SHARING.setValue(!yesNoCheckBoxDialog.isCheckBoxSelected());
return yesNoCheckBoxDialog.isConfirmed();
}
private class RemoveRenderer extends JPanel implements TableCellRenderer {
private final JButton button = new RemoveButton();
public RemoveRenderer() {
super(new BorderLayout());
add(button, BorderLayout.CENTER);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
return this;
}
}
private class RemoveEditor extends JPanel implements TableCellEditor {
private final JButton button = new RemoveButton();
private final List<CellEditorListener> listeners = new ArrayList<CellEditorListener>();
private SharedFileList activeList = null;
public RemoveEditor() {
super(new BorderLayout());
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(showConfirmation(I18n.tr("Remove {0} from list {1}?",
propertiableFile.getFileName(), activeList.getCollectionName()))) {
activeList.removeFile(((LocalFileItem)propertiableFile).getFile());
}
}
});
add(button, BorderLayout.CENTER);
}
@Override
public Component getTableCellEditorComponent(JTable arg0, Object arg1, boolean arg2,
int arg3, int arg4) {
if (arg1 == null) {
return null;
}
activeList = (SharedFileList)arg1;
return this;
}
@Override
public Object getCellEditorValue() {
return activeList;
}
@Override
public void addCellEditorListener(CellEditorListener lis) {
synchronized (listeners) {
if (!listeners.contains(lis))
listeners.add(lis);
}
}
@Override
public void cancelCellEditing() {
synchronized (listeners) {
for (int i = 0, N = listeners.size(); i < N; i++) {
listeners.get(i).editingCanceled(new ChangeEvent(this));
}
}
}
@Override
public boolean isCellEditable(EventObject anEvent) {
return true;
}
@Override
public void removeCellEditorListener(CellEditorListener lis) {
synchronized (listeners) {
if (listeners.contains(lis))
listeners.remove(lis);
}
}
@Override
public boolean shouldSelectCell(EventObject anEvent) {
return false;
}
@Override
public boolean stopCellEditing() {
synchronized (listeners) {
for (int i = 0, N = listeners.size(); i < N; i++) {
listeners.get(i).editingStopped(new ChangeEvent(this));
}
}
return true;
}
}
private static class IconRenderer extends JPanel implements TableCellRenderer {
private static final Border border = BorderFactory.createEmptyBorder(0,5,0,5);
private final JLabel label = new JLabel();
public IconRenderer() {
super(new BorderLayout());
add(label, BorderLayout.CENTER);
setBorder(border);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
label.setIcon((Icon)value);
return this;
}
}
}