package org.infernus.idea.checkstyle.ui;
import com.intellij.openapi.ui.Messages;
import org.infernus.idea.checkstyle.CheckStyleConstants;
import org.infernus.idea.checkstyle.CheckStylePlugin;
import org.infernus.idea.checkstyle.model.ConfigurationLocation;
import org.infernus.idea.checkstyle.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle;
/**
* Provides a configuration panel for project-level configuration.
*
* @author James Shiell
* @version 1.0
*/
public final class CheckStyleConfigPanel extends JPanel {
private final JList pathList = new JList(new DefaultListModel());
private final JButton editPathButton = new JButton(new EditPathAction());
private final JButton removePathButton = new JButton(new RemovePathAction());
private final JButton moveUpPathButton = new JButton(new MoveUpPathAction());
private final JButton moveDownPathButton = new JButton(new MoveDownPathAction());
private final JCheckBox testClassesCheckbox = new JCheckBox();
private final LocationTableModel locationModel = new LocationTableModel();
private final JTable locationTable = new JTable(locationModel);
private final JButton addLocationButton = new JButton(new AddLocationAction());
private final JButton removeLocationButton = new JButton(new RemoveLocationAction());
private final JButton editLocationPropertiesButton = new JButton(new EditPropertiesAction());
private boolean scanTestClasses;
private List<String> thirdPartyClasspath;
private List<ConfigurationLocation> locations;
private ConfigurationLocation activeLocation;
private ConfigurationLocation defaultLocation;
/**
* Plug-in reference.
*/
private CheckStylePlugin plugin;
/**
* Create a new panel.
*
* @param plugin the plugin that owns this panel.
*/
public CheckStyleConfigPanel(final CheckStylePlugin plugin) {
super(new BorderLayout());
if (plugin == null) {
throw new IllegalArgumentException("Plugin may not be null.");
}
this.plugin = plugin;
initialise();
}
/**
* Initialise the view.
*/
private void initialise() {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
final JPanel configFilePanel = buildConfigPanel();
final JPanel pathPanel = buildPathPanel();
final JTabbedPane rootTabPane = new JTabbedPane();
rootTabPane.add(configFilePanel, resources.getString("config.file.tab"));
rootTabPane.add(pathPanel, resources.getString("config.path.tab"));
add(rootTabPane, BorderLayout.CENTER);
}
private JPanel buildConfigPanel() {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
testClassesCheckbox.setText(resources.getString(
"config.test-classes.checkbox.text"));
testClassesCheckbox.setToolTipText(resources.getString(
"config.test-classes.checkbox.tooltip"));
editLocationPropertiesButton.setEnabled(false);
removeLocationButton.setEnabled(false);
final JToolBar locationToolBar = new JToolBar();
locationToolBar.setFloatable(false);
locationToolBar.add(addLocationButton);
locationToolBar.add(editLocationPropertiesButton);
locationToolBar.add(removeLocationButton);
locationTable.getSelectionModel().addListSelectionListener(new LocationTableSelectionListener());
final JScrollPane locationScrollPane = new JScrollPane(locationTable,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
final JPanel locationPanel = new JPanel(new BorderLayout());
locationPanel.add(locationToolBar, BorderLayout.NORTH);
locationPanel.add(locationScrollPane, BorderLayout.CENTER);
final JPanel configFilePanel = new JPanel(new GridBagLayout());
configFilePanel.setBorder(new EmptyBorder(4, 4, 4, 4));
configFilePanel.setOpaque(false);
configFilePanel.add(testClassesCheckbox, new GridBagConstraints(
0, 0, 3, 1, 1.0, 0.0, GridBagConstraints.WEST,
GridBagConstraints.NONE, new Insets(4, 4, 4, 4), 0, 0));
configFilePanel.add(locationPanel, new GridBagConstraints(
0, 1, 3, 1, 1.0, 1.0, GridBagConstraints.WEST,
GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
return configFilePanel;
}
private JPanel buildPathPanel() {
final JButton addPathButton = new JButton(new AddPathAction());
editPathButton.setEnabled(false);
removePathButton.setEnabled(false);
moveUpPathButton.setEnabled(false);
moveDownPathButton.setEnabled(false);
pathList.addListSelectionListener(new PathListSelectionListener());
final JScrollPane pathListScroll = new JScrollPane(pathList);
pathListScroll.setHorizontalScrollBarPolicy(
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
pathListScroll.setVerticalScrollBarPolicy(
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
final JPanel pathPanel = new JPanel(new GridBagLayout());
pathPanel.setBorder(new EmptyBorder(4, 4, 4, 4));
pathPanel.setOpaque(false);
pathPanel.add(pathListScroll, new GridBagConstraints(
0, 0, 1, 7, 1.0, 1.0, GridBagConstraints.NORTHWEST,
GridBagConstraints.BOTH, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(addPathButton, new GridBagConstraints(
1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(editPathButton, new GridBagConstraints(
1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(removePathButton, new GridBagConstraints(
1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(new JSeparator(), new GridBagConstraints(
1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(moveUpPathButton, new GridBagConstraints(
1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(moveDownPathButton, new GridBagConstraints(
1, 5, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
GridBagConstraints.HORIZONTAL, new Insets(4, 4, 4, 4), 0, 0));
pathPanel.add(Box.createVerticalGlue(), new GridBagConstraints(
1, 6, 1, 1, 0.0, 1.0, GridBagConstraints.NORTH,
GridBagConstraints.VERTICAL, new Insets(4, 4, 4, 4), 0, 0));
return pathPanel;
}
/**
* Should we scan test classes?
*
* @param scanTestClasses true to scan test classes.
*/
public void setScanTestClasses(final boolean scanTestClasses) {
this.scanTestClasses = scanTestClasses;
testClassesCheckbox.setSelected(scanTestClasses);
}
/**
* Determine if we should scan test classes.
*
* @return true if test classes should be scanned.
*/
public boolean isScanTestClasses() {
this.scanTestClasses = testClassesCheckbox.isSelected();
return scanTestClasses;
}
/**
* Set the third party classpath.
*
* @param classpath the third party classpath.
*/
public void setThirdPartyClasspath(final List<String> classpath) {
if (classpath == null) {
thirdPartyClasspath = new ArrayList<String>();
} else {
thirdPartyClasspath = classpath;
}
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
listModel.clear();
for (final String classPathFile : thirdPartyClasspath) {
listModel.addElement(classPathFile);
}
}
/**
* Get the third party classpath.
*
* @return the third party classpath.
*/
@NotNull
public List<String> getThirdPartyClasspath() {
final List<String> classpath = new ArrayList<String>();
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
for (int i = 0; i < listModel.size(); ++i) {
final String path = (String) listModel.get(i);
classpath.add(path);
}
return classpath;
}
/**
* Have the settings been modified?
*
* @return true if the settngs have been modified.
*/
public boolean isModified() {
return !ObjectUtils.equals(locations, locationModel.getLocations())
|| !ObjectUtils.equals(activeLocation, locationModel.getActiveLocation())
|| !getThirdPartyClasspath().equals(thirdPartyClasspath)
|| testClassesCheckbox.isSelected() != scanTestClasses;
}
public List<ConfigurationLocation> getConfigurationLocations() {
return Collections.unmodifiableList(locationModel.getLocations());
}
public void setConfigurationLocations(final List<ConfigurationLocation> locations) {
this.locations = locations;
locationModel.setLocations(locations);
}
public void setActiveLocation(final ConfigurationLocation activeLocation) {
this.activeLocation = activeLocation;
locationModel.setActiveLocation(activeLocation);
}
public ConfigurationLocation getActiveLocation() {
return locationModel.getActiveLocation();
}
public void setDefaultLocation(final ConfigurationLocation defaultLocation) {
this.defaultLocation = defaultLocation;
}
/**
* Process the addition of a configuration location.
*/
protected final class AddLocationAction extends AbstractAction {
private static final long serialVersionUID = -7266120887003483814L;
public AddLocationAction() {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString("config.file.add.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.file.add.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.file.add.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final LocationDialogue dialogue = new LocationDialogue(plugin.getProject());
dialogue.setVisible(true);
if (dialogue.isCommitted()) {
final ConfigurationLocation newLocation = dialogue.getConfigurationLocation();
if (locationModel.getLocations().contains(newLocation)) {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
Messages.showWarningDialog(plugin.getProject(),
resources.getString("config.file.error.duplicate.text"),
resources.getString("config.file.error.duplicate.title"));
} else {
locationModel.addLocation(dialogue.getConfigurationLocation());
}
}
}
}
/**
* Process the removal of a configuration location.
*/
protected final class RemoveLocationAction extends AbstractAction {
private static final long serialVersionUID = -799542186049804472L;
public RemoveLocationAction() {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString("config.file.remove.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.file.remove.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.file.remove.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final int selectedIndex = locationTable.getSelectedRow();
if (selectedIndex == -1) {
return;
}
locationModel.removeLocationAt(selectedIndex);
}
}
/**
* Edit the properties of a configuration location.
*/
protected final class EditPropertiesAction extends AbstractAction {
private static final long serialVersionUID = -799542186049804472L;
public EditPropertiesAction() {
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString("config.file.properties.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.file.properties.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.file.properties.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final int selectedIndex = locationTable.getSelectedRow();
if (selectedIndex == -1) {
return;
}
final ConfigurationLocation location = locationModel.getLocationAt(selectedIndex);
final PropertiesDialogue propertiesDialogue = new PropertiesDialogue(plugin.getProject());
propertiesDialogue.setConfigurationLocation(location);
propertiesDialogue.setVisible(true);
if (propertiesDialogue.isCommitted()) {
final ConfigurationLocation editedLocation = propertiesDialogue.getConfigurationLocation();
locationModel.updateLocation(location, editedLocation);
}
}
}
/**
* Location table selection listener.
*/
protected final class LocationTableSelectionListener
implements ListSelectionListener {
/**
* {@inheritDoc}
*/
public void valueChanged(final ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
final int selectedItem = locationTable.getSelectedRow();
if (selectedItem == -1) {
editLocationPropertiesButton.setEnabled(false);
removeLocationButton.setEnabled(false);
} else {
final ConfigurationLocation location = locationModel.getLocationAt(selectedItem);
editLocationPropertiesButton.setEnabled(!ObjectUtils.equals(location, defaultLocation));
removeLocationButton.setEnabled(!ObjectUtils.equals(location, defaultLocation));
}
}
}
/**
* Path list selection listener.
*/
protected final class PathListSelectionListener
implements ListSelectionListener {
/**
* {@inheritDoc}
*/
public void valueChanged(final ListSelectionEvent e) {
if (e.getValueIsAdjusting()) {
return;
}
final int[] selectedItems = pathList.getSelectedIndices();
final boolean single = selectedItems != null
&& selectedItems.length == 1;
final boolean multiple = selectedItems != null
&& selectedItems.length > 1;
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
editPathButton.setEnabled(single);
removePathButton.setEnabled(single || multiple);
moveUpPathButton.setEnabled(single && pathList.getSelectedIndex()
!= 0);
moveDownPathButton.setEnabled(single && pathList.getSelectedIndex()
!= (listModel.getSize() - 1));
}
}
/**
* Process the addition of a path element.
*/
protected final class AddPathAction extends AbstractAction {
/**
* Create a new add path action.
*/
public AddPathAction() {
super();
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString("config.path.add.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.path.add.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.path.add.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new ExtensionFileFilter("jar"));
fileChooser.setFileSelectionMode(
JFileChooser.FILES_AND_DIRECTORIES);
final int result = fileChooser.showOpenDialog(
CheckStyleConfigPanel.this);
if (result == JFileChooser.APPROVE_OPTION) {
((DefaultListModel) pathList.getModel()).addElement(
fileChooser.getSelectedFile().getAbsolutePath());
}
}
}
/**
* Process the editing of a path element.
*/
protected final class EditPathAction extends AbstractAction {
/**
* Create a new edit path action.
*/
public EditPathAction() {
super();
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString("config.path.edit.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.path.edit.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.path.edit.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final int selected = pathList.getSelectedIndex();
if (selected < 1) {
return;
}
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
final String selectedFile = (String) listModel.get(selected);
final JFileChooser fileChooser = new JFileChooser();
fileChooser.setFileFilter(new ExtensionFileFilter("jar"));
fileChooser.setSelectedFile(new File(selectedFile));
fileChooser.setFileSelectionMode(
JFileChooser.FILES_AND_DIRECTORIES);
final int result = fileChooser.showOpenDialog(
CheckStyleConfigPanel.this);
if (result == JFileChooser.APPROVE_OPTION) {
listModel.remove(selected);
listModel.add(selected,
fileChooser.getSelectedFile().getAbsolutePath());
pathList.setSelectedIndex(selected);
}
}
}
/**
* Process the removal of a path element.
*/
protected final class RemovePathAction extends AbstractAction {
/**
* Create a new add path action.
*/
public RemovePathAction() {
super();
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString(
"config.path.remove.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.path.remove.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.path.remove.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final int[] selected = pathList.getSelectedIndices();
if (selected == null || selected.length == 0) {
return;
}
for (final int index : selected) {
((DefaultListModel) pathList.getModel()).remove(index);
}
}
}
/**
* Process the move up of a path element.
*/
protected final class MoveUpPathAction extends AbstractAction {
/**
* Create a new move-up path action.
*/
public MoveUpPathAction() {
super();
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString(
"config.path.move-up.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.path.move-up.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.path.move-up.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final int selected = pathList.getSelectedIndex();
if (selected < 1) {
return;
}
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
final Object element = listModel.remove(selected);
listModel.add(selected - 1, element);
pathList.setSelectedIndex(selected - 1);
}
}
/**
* Process a click on the browse button.
*/
/**
* Process the move down of a path element.
*/
protected final class MoveDownPathAction extends AbstractAction {
/**
* Create a new move-down path action.
*/
public MoveDownPathAction() {
super();
final ResourceBundle resources = ResourceBundle.getBundle(
CheckStyleConstants.RESOURCE_BUNDLE);
putValue(Action.NAME, resources.getString(
"config.path.move-down.text"));
putValue(Action.SHORT_DESCRIPTION,
resources.getString("config.path.move-down.tooltip"));
putValue(Action.LONG_DESCRIPTION,
resources.getString("config.path.move-down.tooltip"));
}
/**
* {@inheritDoc}
*/
public void actionPerformed(final ActionEvent e) {
final DefaultListModel listModel = (DefaultListModel)
pathList.getModel();
final int selected = pathList.getSelectedIndex();
if (selected == -1 || selected == (listModel.getSize() - 1)) {
return;
}
final Object element = listModel.remove(selected);
listModel.add(selected + 1, element);
pathList.setSelectedIndex(selected + 1);
}
}
}
|