package org.kalisen.classpathdoctor.gui;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.util.Observable;
import java.util.Observer;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DocumentFilter;
import javax.swing.text.PlainDocument;
import org.kalisen.classpathdoctor.ClassPath;
import org.kalisen.classpathdoctor.adapter.ClassPathAdapter;
import org.kalisen.classpathdoctor.adapter.DefaultClassPathAdapter;
import org.kalisen.classpathdoctor.gui.actions.AddAnEntryAction;
import org.kalisen.classpathdoctor.gui.actions.MoveDownAction;
import org.kalisen.classpathdoctor.gui.actions.MoveUpAction;
import org.kalisen.classpathdoctor.gui.actions.RemoveAnEntryAction;
import org.kalisen.common.DefaultErrorHandler;
import org.kalisen.common.ErrorHandler;
@SuppressWarnings("serial")
public class ClassPathPanel extends JPanel {
private ErrorHandler errorHandler = null;
private ClassPathList pathsList = null;
private JTextArea classpathTextArea = null;
private JButton addButton = null;
private JButton removeButton = null;
private JButton moveUpButton = null;
private JButton moveDownButton = null;
private ClassPathListModel classpathListModel = null;
private ClassPathAdapter adapter = null;
private final DocumentListener textAreaListener = new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
notifyAdapter(e);
}
public void insertUpdate(DocumentEvent e) {
notifyAdapter(e);
}
public void removeUpdate(DocumentEvent e) {
notifyAdapter(e);
}
private void notifyAdapter(final DocumentEvent e) {
try {
getAdapter()
.setClassPathAsText(
e.getDocument().getText(0,
e.getDocument().getLength()));
} catch (BadLocationException ble) {
handleError(ble);
}
}
};
private final Observer adapterListenerForList = new Observer() {
public void update(Observable o, final Object arg) {
if (arg instanceof ClassPath) {
ClassPathPanel.this.classpathListModel
.setClassPath(getAdapter().getClassPath());
ClassPathPanel.this.pathsList.repaint();
}
}
};
private final Observer adapterListenerForButtons = new Observer() {
public void update(Observable o, final Object arg) {
if (arg instanceof ClassPath) {
ClassPath cp = getAdapter().getClassPath();
boolean shouldBeEnabled = cp.getEntries().size() > 0
&& ClassPathPanel.this.pathsList
.getSelectedIndices().length > 0;
if (ClassPathPanel.this.removeButton.isEnabled() != shouldBeEnabled) {
ClassPathPanel.this.removeButton
.setEnabled(shouldBeEnabled);
}
if (ClassPathPanel.this.moveUpButton.isEnabled() != shouldBeEnabled) {
ClassPathPanel.this.moveUpButton
.setEnabled(shouldBeEnabled);
}
if (ClassPathPanel.this.moveDownButton.isEnabled() != shouldBeEnabled) {
ClassPathPanel.this.moveDownButton
.setEnabled(shouldBeEnabled);
}
}
}
};
private final Observer adapterListenerForTextArea = new Observer() {
public void update(Observable o, final Object arg) {
if (!ClassPathPanel.this.classpathTextArea.getText().equals(
getAdapter().getClassPathAsText())) {
ClassPathPanel.this.classpathTextArea.setText(getAdapter()
.getClassPathAsText());
}
}
};
private final ListSelectionListener listListenerForButtons = new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
if (!e.getValueIsAdjusting()) {
boolean moveUpShouldBeEnabled = e.getFirstIndex() > 0;
if (ClassPathPanel.this.moveUpButton.isEnabled() != moveUpShouldBeEnabled) {
ClassPathPanel.this.moveUpButton
.setEnabled(moveUpShouldBeEnabled);
}
boolean moveDownShouldBeEnabled = e.getLastIndex() < ClassPathPanel.this.classpathListModel
.getSize() - 1;
if (ClassPathPanel.this.moveDownButton.isEnabled() != moveDownShouldBeEnabled) {
ClassPathPanel.this.moveDownButton
.setEnabled(moveDownShouldBeEnabled);
}
boolean removeShouldBeEnabled = ClassPathPanel.this.pathsList
.getSelectedIndices().length > 0;
if (ClassPathPanel.this.removeButton.isEnabled() != removeShouldBeEnabled) {
ClassPathPanel.this.removeButton
.setEnabled(removeShouldBeEnabled);
}
}
}
};
private final ListDataListener listDataListenerForAdapter = new ListDataListener() {
public void intervalRemoved(ListDataEvent e) {
contentsChanged(e);
}
public void intervalAdded(ListDataEvent e) {
contentsChanged(e);
}
public void contentsChanged(ListDataEvent e) {
getAdapter().setClassPath(
ClassPathPanel.this.classpathListModel.getClassPath());
}
};
public ClassPathPanel() {
init();
}
private void init() {
setLayout(new BorderLayout());
setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
this.pathsList = buildListComponent();
this.classpathTextArea = buildTextComponent();
JPanel buttonPanel = buildButtonPanel();
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
splitPane.setDividerLocation(.8);
splitPane.setResizeWeight(.8);
JScrollPane listScrollPane = new JScrollPane(this.pathsList);
splitPane.add(listScrollPane, JSplitPane.TOP);
JScrollPane textScrollPane = new JScrollPane(this.classpathTextArea);
splitPane.add(textScrollPane, JSplitPane.BOTTOM);
add(splitPane, BorderLayout.CENTER);
add(buttonPanel, BorderLayout.EAST);
initListeners();
}
private void initListeners() {
this.classpathTextArea.getDocument().addDocumentListener(
this.textAreaListener);
getAdapter().addListener(this.adapterListenerForList);
getAdapter().addListener(this.adapterListenerForTextArea);
getAdapter().addListener(this.adapterListenerForButtons);
this.pathsList
.addListSelectionListener(this.listListenerForButtons);
this.classpathListModel
.addListDataListener(this.listDataListenerForAdapter);
}
private JPanel buildButtonPanel() {
JPanel result = new JPanel();
result.setLayout(new BoxLayout(result, BoxLayout.Y_AXIS));
result.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
result.add(Box.createVerticalGlue());
this.moveUpButton = new JButton(new MoveUpAction(this.pathsList,
this.classpathListModel));
this.moveUpButton.setName("MOVE_UP");
this.moveUpButton.setMaximumSize(new Dimension(Integer.MAX_VALUE,
this.moveUpButton.getSize().height));
this.moveUpButton.setEnabled(false);
result.add(this.moveUpButton);
this.moveDownButton = new JButton(new MoveDownAction(
this.pathsList, this.classpathListModel));
this.moveDownButton.setName("MOVE_DOWN");
this.moveDownButton.setMaximumSize(new Dimension(Integer.MAX_VALUE,
this.moveDownButton.getSize().height));
this.moveDownButton.setEnabled(false);
result.add(this.moveDownButton);
result.add(Box.createVerticalStrut(5));
this.addButton = new JButton(new AddAnEntryAction(this, getAdapter()));
this.addButton.setName("ADD_ENTRY");
this.addButton.setMaximumSize(new Dimension(Integer.MAX_VALUE,
this.addButton.getSize().height));
result.add(this.addButton);
this.removeButton = new JButton(new RemoveAnEntryAction(
this.pathsList, getAdapter()));
this.removeButton.setName("REMOVE_ENTRY");
this.removeButton.setMaximumSize(new Dimension(Integer.MAX_VALUE,
this.removeButton.getSize().height));
this.removeButton.setEnabled(false);
result.add(this.removeButton);
result.add(Box.createVerticalGlue());
return result;
}
private JTextArea buildTextComponent() {
JTextArea result = new JTextArea();
PlainDocument doc = new PlainDocument();
doc.setDocumentFilter(new DocumentFilter() {
@Override
public void insertString(FilterBypass fb, int offset,
String string, AttributeSet attr)
throws BadLocationException {
if ("\n".equals(string)) {
return; // don't insert any new lines
}
super.insertString(fb, offset, string, attr);
}
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs)
throws BadLocationException {
if (length > 0) {
fb.remove(offset, length);
}
insertString(fb, offset, text, null);
}
});
result.setDocument(doc);
result.setWrapStyleWord(true);
result.setLineWrap(true);
return result;
}
private ClassPathList buildListComponent() {
this.classpathListModel = new ClassPathListModel();
return new ClassPathList(this.classpathListModel);
}
public ClassPathAdapter getAdapter() {
if (this.adapter == null) {
this.adapter = new DefaultClassPathAdapter();
}
return this.adapter;
}
public void setAdapter(ClassPathAdapter adapter) {
if (adapter == null) {
throw new IllegalArgumentException("null is not a valid argument");
}
this.adapter = adapter;
}
public void handleError(Throwable t) {
this.errorHandler.handleError(t);
}
public ErrorHandler getErrorHandler() {
if (this.errorHandler == null) {
this.errorHandler = new DefaultErrorHandler();
}
return this.errorHandler;
}
public void setErrorHandler(ErrorHandler handler) {
if (handler == null) {
throw new IllegalArgumentException("null is not a valid argument");
}
this.errorHandler = handler;
}
}