package org.limewire.ui.swing.library.navigator;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
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.JLabel;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;
import net.miginfocom.swing.MigLayout;
import org.jdesktop.application.Resource;
import org.limewire.core.api.library.SharedFileList;
import org.limewire.ui.swing.components.TextFieldClipboardControl;
import org.limewire.ui.swing.library.navigator.LibraryNavItem.NavType;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.util.OSUtils;
class LibraryNavTableEditor extends JPanel implements TableCellEditor {
private @Resource Color selectedColor;
private @Resource Font font;
private @Resource Color fontColor;
private @Resource int iconGap;
private @Resource Icon libraryIcon;
private @Resource Icon publicIcon;
private @Resource Icon listIcon;
private @Resource Icon listSharedIcon;
private final List<CellEditorListener> listeners = new ArrayList<CellEditorListener>();
private final JLabel iconHolder;
private final JTextField textField;
public LibraryNavTableEditor() {
super(new MigLayout("gap 0, insets 0 6 0 6, fill"));
GuiUtils.assignResources(this);
iconHolder = new JLabel();
textField = new JTextField();
TextFieldClipboardControl.install(textField);
textField.setPreferredSize(new Dimension(120, 22));
textField.setFont(font);
textField.setForeground(fontColor);
textField.setDocument(new TextFieldLimit(40));
textField.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
// OSX paints a giant blue border when selected which takes up too much room
// for the table row height
if(OSUtils.isMacOSX())
textField.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
setBackground(selectedColor);
add(iconHolder, "aligny 50%, gapright " + iconGap);
add(textField, "growx");
}
void prepareForEditing() {
textField.requestFocusInWindow();
textField.selectAll();
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected,
int row, int column) {
if(value instanceof LibraryNavItem) {
LibraryNavItem item = (LibraryNavItem) value;
textField.setText(item.getDisplayText());
textField.selectAll();
setIconType(item);
} else {
textField.setText("");
iconHolder.setIcon(null);
}
setOpaque(isSelected);
return this;
}
private void setIconType(LibraryNavItem item) {
if(item.getType() == NavType.LIBRARY)
iconHolder.setIcon(libraryIcon);
else if(item.getType() == NavType.PUBLIC_SHARED)
iconHolder.setIcon(publicIcon);
else {
if(item.getLocalFileList() instanceof SharedFileList) {
if(((SharedFileList)item.getLocalFileList()).getFriendIds().size() > 0)
iconHolder.setIcon(listSharedIcon);
else
iconHolder.setIcon(listIcon);
} else {
iconHolder.setIcon(listIcon);
}
}
}
@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 Object getCellEditorValue() {
return textField.getText().trim();
}
@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 true;
}
@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;
}
/**
* Sets the max limit for a shared file list name.
*/
private static class TextFieldLimit extends PlainDocument {
private int maxLength;
TextFieldLimit(int maxLength) {
this.maxLength = maxLength;
}
@Override
public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
if(str == null)
return;
if((getLength() + str.length()) < maxLength) {
super.insertString(offset, str, attr);
}
}
}
}