package org.infernus.idea.checkstyle.ui;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.util.ui.JBUI;
import org.infernus.idea.checkstyle.CheckStyleBundle;
import org.infernus.idea.checkstyle.model.ConfigurationLocation;
import org.infernus.idea.checkstyle.util.Icons;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static com.intellij.util.ui.JBUI.*;
/**
* Provides module level configuration UI.
*/
public class CheckStyleModuleConfigPanel extends JPanel {
private static final Insets ISOLATED_COMPONENT_INSETS = JBUI.insets(8);
private final JRadioButton useProjectConfigurationRadio = new JRadioButton();
private final JRadioButton useModuleConfigurationRadio = new JRadioButton();
private final JRadioButton excludeRadio = new JRadioButton();
private final ComboBox configurationFilesCombo = new ComboBox();
private final DefaultComboBoxModel<ConfigurationLocation> configurationFilesModel = new DefaultComboBoxModel<>();
private final JLabel configurationFilesLabel = new JLabel();
private List<ConfigurationLocation> configurationLocations;
private ConfigurationLocation activeLocation;
private boolean excluded;
/**
* Create a new panel.
*/
public CheckStyleModuleConfigPanel() {
super(new BorderLayout());
initialise();
}
private void initialise() {
add(buildConfigurationPanel(), BorderLayout.CENTER);
}
private JPanel buildConfigurationPanel() {
final JPanel configPanel = new JPanel(new GridBagLayout());
final JLabel informationLabel = new JLabel(CheckStyleBundle.message("config.module.information"),
Icons.icon("/general/information.png"), SwingConstants.LEFT);
configPanel.add(informationLabel, new GridBagConstraints(0, 0, 2, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, JBUI.insets(16, 8), 0, 0));
useProjectConfigurationRadio.setText(CheckStyleBundle.message("config.module.project-configuration.text"));
useProjectConfigurationRadio.setToolTipText(CheckStyleBundle.message("config.module.project-configuration.tooltip"));
useProjectConfigurationRadio.addActionListener(new RadioListener());
useModuleConfigurationRadio.setText(CheckStyleBundle.message("config.module.module-configuration.text"));
useModuleConfigurationRadio.setToolTipText(CheckStyleBundle.message("config.module.module-configuration.tooltip"));
useModuleConfigurationRadio.addActionListener(new RadioListener());
excludeRadio.setText(CheckStyleBundle.message("config.module.exclude.text"));
excludeRadio.setToolTipText(CheckStyleBundle.message("config.module.exclude.tooltip"));
excludeRadio.addActionListener(new RadioListener());
final ButtonGroup radioGroup = new ButtonGroup();
radioGroup.add(useProjectConfigurationRadio);
radioGroup.add(useModuleConfigurationRadio);
radioGroup.add(excludeRadio);
configPanel.add(useProjectConfigurationRadio, new GridBagConstraints(0, 1, 2, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, ISOLATED_COMPONENT_INSETS, 0, 0));
configPanel.add(useModuleConfigurationRadio, new GridBagConstraints(0, 2, 2, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, ISOLATED_COMPONENT_INSETS, 0, 0));
configurationFilesLabel.setText(CheckStyleBundle.message("config.module.module-file.text"));
configPanel.add(configurationFilesLabel, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0,
GridBagConstraints.EAST, GridBagConstraints.NONE, JBUI.insets(8, 32, 8, 8), 0, 0));
configurationFilesCombo.setToolTipText(CheckStyleBundle.message("config.module.module-file.tooltip"));
//noinspection unchecked
configurationFilesCombo.setModel(configurationFilesModel);
configPanel.add(configurationFilesCombo, new GridBagConstraints(1, 3, 1, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, ISOLATED_COMPONENT_INSETS, 0, 0));
configPanel.add(excludeRadio, new GridBagConstraints(0, 4, 2, 1, 1.0, 0.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, ISOLATED_COMPONENT_INSETS, 0, 0));
configPanel.add(Box.createGlue(), new GridBagConstraints(0, 5, 2, 1, 1.0, 1.0,
GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, emptyInsets(), 0, 0));
useProjectConfigurationRadio.setSelected(true);
configurationFilesLabel.setEnabled(false);
configurationFilesCombo.setEnabled(false);
return configPanel;
}
private List<ConfigurationLocation> getConfigurationLocations() {
final List<ConfigurationLocation> locations = new ArrayList<>();
for (int i = 0; i < configurationFilesModel.getSize(); ++i) {
locations.add(configurationFilesModel.getElementAt(i));
}
return Collections.unmodifiableList(locations);
}
public void setConfigurationLocations(final List<ConfigurationLocation> locations) {
this.configurationLocations = locations;
configurationFilesModel.removeAllElements();
if (locations != null && !locations.isEmpty()) {
locations.forEach(configurationFilesModel::addElement);
configurationFilesModel.setSelectedItem(locations.get(0));
}
useModuleConfigurationRadio.setEnabled(locations != null && !locations.isEmpty());
}
/**
* Set the configuration to use, or null to use the project configuration.
*
* @param activeLocation the configuration, or null to use the project configuration.
*/
public void setActiveLocation(@Nullable final ConfigurationLocation activeLocation) {
this.activeLocation = activeLocation;
if (activeLocation != null) {
configurationFilesCombo.setSelectedItem(activeLocation);
} else if (configurationFilesModel.getSize() > 0) {
configurationFilesCombo.setSelectedItem(configurationFilesModel.getElementAt(0));
}
if (activeLocation != null) {
useModuleConfigurationRadio.setSelected(true);
} else if (!excluded) {
useProjectConfigurationRadio.setSelected(true);
}
new RadioListener().actionPerformed(null);
}
/**
* Get the configuration to use, or null to use the project configuration.
*
* @return the configuration, or null to use the project configuration.
*/
public ConfigurationLocation getActiveLocation() {
if (useProjectConfigurationRadio.isSelected() || excludeRadio.isSelected()) {
return null;
}
return (ConfigurationLocation) configurationFilesModel.getSelectedItem();
}
public void setExcluded(final boolean excluded) {
this.excluded = excluded;
if (excluded) {
excludeRadio.setSelected(true);
}
}
public boolean isExcluded() {
return excludeRadio.isSelected();
}
/**
* Have the contents been modified since being set?
*
* @return true if modified.
*/
public boolean isModified() {
return !equals(activeLocation, getActiveLocation())
|| !equals(configurationLocations, getConfigurationLocations())
|| excluded != isExcluded();
}
/*
* This is a port from commons-lang 2.4, in order to get around the absence of commons-lang in
* some packages of IDEA 7.x.
*/
private boolean equals(final Object object1, final Object object2) {
if (object1 == object2) {
return true;
}
if ((object1 == null) || (object2 == null)) {
return false;
}
return object1.equals(object2);
}
/**
* Listener to update UI based on radio button selections.
*/
private class RadioListener implements ActionListener {
@Override
public void actionPerformed(final ActionEvent e) {
final boolean showModuleConfig = useModuleConfigurationRadio.isSelected();
configurationFilesLabel.setEnabled(showModuleConfig);
configurationFilesCombo.setEnabled(showModuleConfig);
}
}
}