/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.maddyhome.idea.copyright.ui;
import com.intellij.lang.Commenter;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorFontType;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.ui.DocumentAdapter;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.util.ui.UIUtil;
import com.maddyhome.idea.copyright.CopyrightManager;
import com.maddyhome.idea.copyright.CopyrightProfile;
import com.maddyhome.idea.copyright.CopyrightUpdaters;
import com.maddyhome.idea.copyright.pattern.EntityUtil;
import com.maddyhome.idea.copyright.pattern.VelocityHelper;
import com.maddyhome.idea.copyright.util.FileTypeUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import consulo.copyright.config.CopyrightFileConfig;
import consulo.copyright.config.CopyrightFileConfigManager;
import consulo.copyright.generate.TemplateCopyrightCommenter;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.EventListenerList;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class TemplateCommentPanel implements SearchableConfigurable {
private final CopyrightManager myManager;
private final TemplateCommentPanel parentPanel;
private final String myOptionName;
private final EventListenerList listeners = new EventListenerList();
private JRadioButton[] fileLocations = null;
private JTextArea preview;
private JPanel mainPanel;
private JRadioButton rbBefore;
private JRadioButton rbAfter;
private JPanel fileLocationPanel;
private JRadioButton myUseDefaultSettingsRadioButton;
private JRadioButton myUseCustomFormattingOptionsRadioButton;
private JRadioButton myNoCopyright;
private JRadioButton rbLineComment;
private JCheckBox cbPrefixLines;
private JRadioButton rbBlockComment;
private JPanel myCommentTypePanel;
private JCheckBox cbSeparatorBefore;
private JTextField txtLengthBefore;
private JTextField txtLengthAfter;
private JCheckBox cbAddBlank;
private JCheckBox cbSeparatorAfter;
private JCheckBox cbBox;
private JTextField txtFiller;
private JPanel myBorderPanel;
private JLabel lblLengthBefore;
private JLabel lblLengthAfter;
private JLabel mySeparatorCharLabel;
private JPanel myAdditionalPanel;
private boolean myAllowBlock;
private Commenter myCommenter;
private boolean myAllowSeparator;
private FileType myFileType;
public TemplateCommentPanel(@NotNull FileType fileType, @Nullable TemplateCommentPanel parentPanel, @NotNull Project project) {
this(fileType.getName(), parentPanel, project);
myAllowBlock = FileTypeUtil.hasBlockComment(fileType);
myCommenter = FileTypeUtil.getCommenter(fileType);
myAllowSeparator = CopyrightUpdaters.INSTANCE.forFileType(fileType).isAllowSeparator();
myFileType = fileType;
}
public TemplateCommentPanel(@NotNull String optionName, @Nullable TemplateCommentPanel parentPanel, @NotNull Project project) {
this.parentPanel = parentPanel;
myOptionName = optionName;
myManager = CopyrightManager.getInstance(project);
// no comboboxes for template
if (optionName.equals(CopyrightFileConfigManager.LANG_TEMPLATE)) {
myUseDefaultSettingsRadioButton.setVisible(false);
myUseCustomFormattingOptionsRadioButton.setVisible(false);
myNoCopyright.setVisible(false);
myCommenter = TemplateCopyrightCommenter.INSTANCE;
myAllowBlock = true;
myAllowSeparator = true;
}
if (parentPanel != null) {
parentPanel.addOptionChangeListener(new TemplateOptionsPanelListener() {
@Override
public void optionChanged() {
updateOverride();
}
});
}
ButtonGroup group = new ButtonGroup();
group.add(rbBefore);
group.add(rbAfter);
fileLocationPanel.setBorder(BorderFactory.createEmptyBorder());
addAdditionalComponents(myAdditionalPanel);
addOptionChangeListener(new TemplateOptionsPanelListener() {
@Override
public void optionChanged() {
showPreview(getOptions());
}
});
preview.setFont(EditorColorsManager.getInstance().getGlobalScheme().getFont(EditorFontType.PLAIN));
myUseDefaultSettingsRadioButton.setSelected(true);
final ActionListener listener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updateOverride();
}
};
myUseDefaultSettingsRadioButton.addActionListener(listener);
myUseCustomFormattingOptionsRadioButton.addActionListener(listener);
myNoCopyright.addActionListener(listener);
txtLengthBefore.setText("80");
txtLengthAfter.setText("80");
rbBlockComment.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
cbPrefixLines.setEnabled(rbBlockComment.isSelected());
fireChangeEvent();
}
});
rbLineComment.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
cbPrefixLines.setEnabled(rbBlockComment.isSelected());
fireChangeEvent();
}
});
cbPrefixLines.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
fireChangeEvent();
}
});
cbSeparatorBefore.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
lblLengthBefore.setEnabled(cbSeparatorBefore.isSelected());
txtLengthBefore.setEnabled(cbSeparatorBefore.isSelected());
fireChangeEvent();
updateBox();
}
});
cbSeparatorAfter.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
lblLengthAfter.setEnabled(cbSeparatorAfter.isSelected());
txtLengthAfter.setEnabled(cbSeparatorAfter.isSelected());
fireChangeEvent();
updateBox();
}
});
final DocumentAdapter documentAdapter = new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
fireChangeEvent();
updateBox();
}
};
txtLengthBefore.getDocument().addDocumentListener(documentAdapter);
txtLengthAfter.getDocument().addDocumentListener(documentAdapter);
txtFiller.getDocument().addDocumentListener(documentAdapter);
cbBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
fireChangeEvent();
}
});
}
private void updateBox() {
boolean enable = true;
if (!cbSeparatorBefore.isSelected()) {
enable = false;
}
else if (!cbSeparatorAfter.isSelected()) {
enable = false;
}
else {
if (!txtLengthBefore.getText().equals(txtLengthAfter.getText())) {
enable = false;
}
}
boolean either = cbSeparatorBefore.isSelected() || cbSeparatorAfter.isSelected();
cbBox.setEnabled(enable);
txtFiller.setEnabled(either);
}
public void addAdditionalComponents(@NotNull JPanel additionalPanel) {
}
public void addLocationInFile(@NotNull String[] locations) {
fileLocationPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Location in File"));
fileLocations = new JRadioButton[locations.length];
ButtonGroup group = new ButtonGroup();
for (int i = 0; i < fileLocations.length; i++) {
fileLocations[i] = new JRadioButton(locations[i]);
group.add(fileLocations[i]);
fileLocationPanel.add(fileLocations[i], new GridConstraints(i, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_FIXED, null, null, null));
}
}
public CopyrightFileConfig getOptions() {
// If this is a fully custom comment we should really ensure there are no blank lines in the comments outside
// of a block comment. If there are any blank lines the replacement logic will fall apart.
final CopyrightFileConfig res = myFileType == null ? new CopyrightFileConfig() : CopyrightUpdaters.INSTANCE.forFileType(myFileType).createDefaultOptions();
res.setBlock(rbBlockComment.isSelected());
res.setPrefixLines(!myAllowBlock || cbPrefixLines.isSelected());
res.setSeparateAfter(cbSeparatorAfter.isSelected());
res.setSeparateBefore(cbSeparatorBefore.isSelected());
try {
Object val = Integer.parseInt(txtLengthBefore.getText());
if (val instanceof Number) {
res.setLenBefore(((Number)val).intValue());
}
val = Integer.parseInt(txtLengthAfter.getText());
if (val instanceof Number) {
res.setLenAfter(((Number)val).intValue());
}
}
catch (NumberFormatException e) {
//leave blank
}
res.setBox(cbBox.isSelected());
String filler = txtFiller.getText();
if (filler.length() > 0) {
res.setFiller(filler);
}
else {
res.setFiller(CopyrightFileConfig.DEFAULT_FILLER);
}
res.setFileTypeOverride(getOverrideChoice());
res.setRelativeBefore(rbBefore.isSelected());
res.setAddBlankAfter(cbAddBlank.isSelected());
if (fileLocations != null) {
for (int i = 0; i < fileLocations.length; i++) {
if (fileLocations[i].isSelected()) {
res.setFileLocation(i + 1);
}
}
}
return res;
}
private int getOverrideChoice() {
return myUseDefaultSettingsRadioButton.isSelected()
? CopyrightFileConfig.USE_TEMPLATE
: myNoCopyright.isSelected() ? CopyrightFileConfig.NO_COPYRIGHT : CopyrightFileConfig.USE_TEXT;
}
private void updateOverride() {
int choice = getOverrideChoice();
CopyrightFileConfig parentOpts = parentPanel != null ? parentPanel.getOptions() : null;
switch (choice) {
case CopyrightFileConfig.NO_COPYRIGHT:
enableFormattingOptions(false);
showPreview(getOptions());
rbBefore.setEnabled(false);
rbAfter.setEnabled(false);
cbAddBlank.setEnabled(false);
if (fileLocations != null) {
for (JRadioButton fileLocation : fileLocations) {
fileLocation.setEnabled(false);
}
}
break;
case CopyrightFileConfig.USE_TEMPLATE:
final boolean isTemplate = parentPanel == null;
enableFormattingOptions(isTemplate);
showPreview(parentOpts != null ? parentOpts : getOptions());
rbBefore.setEnabled(isTemplate);
rbAfter.setEnabled(isTemplate);
cbAddBlank.setEnabled(isTemplate);
if (fileLocations != null) {
for (JRadioButton fileLocation : fileLocations) {
fileLocation.setEnabled(true);
}
}
break;
case CopyrightFileConfig.USE_TEXT:
enableFormattingOptions(true);
showPreview(getOptions());
rbBefore.setEnabled(true);
rbAfter.setEnabled(true);
cbAddBlank.setEnabled(true);
if (fileLocations != null) {
for (JRadioButton fileLocation : fileLocations) {
fileLocation.setEnabled(true);
}
}
break;
}
}
private void enableFormattingOptions(boolean enable) {
if (enable) {
rbBlockComment.setEnabled(true);
rbLineComment.setEnabled(true);
cbPrefixLines.setEnabled(myAllowBlock);
cbSeparatorBefore.setEnabled(true);
cbSeparatorAfter.setEnabled(true);
lblLengthBefore.setEnabled(cbSeparatorBefore.isSelected());
txtLengthBefore.setEnabled(cbSeparatorBefore.isSelected());
lblLengthAfter.setEnabled(cbSeparatorAfter.isSelected());
txtLengthAfter.setEnabled(cbSeparatorAfter.isSelected());
mySeparatorCharLabel.setEnabled(true);
updateBox();
}
else {
UIUtil.setEnabled(myCommentTypePanel, enable, true);
UIUtil.setEnabled(myBorderPanel, enable, true);
}
}
private void showPreview(CopyrightFileConfig options) {
final String defaultCopyrightText;
if (myNoCopyright.isSelected()) {
defaultCopyrightText = "";
}
else {
String evaluate;
try {
evaluate = VelocityHelper.evaluate(null, null, null, EntityUtil.decode(CopyrightProfile.DEFAULT_COPYRIGHT_NOTICE));
}
catch (Exception e) {
evaluate = "";
}
defaultCopyrightText = FileTypeUtil.buildComment(myCommenter, myAllowSeparator, evaluate, options);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
preview.setText(defaultCopyrightText);
}
});
}
@Override
@Nls
public String getDisplayName() {
return myOptionName;
}
@Override
public String getHelpTopic() {
return "copyright.filetypes";
}
@Override
public JComponent createComponent() {
return mainPanel;
}
@Override
public boolean isModified() {
if (myFileType == null) {
return !myManager.getCopyrightFileConfigManager().getTemplateOptions().equals(getOptions());
}
else {
return !myManager.getCopyrightFileConfigManager().getOptions(myFileType).equals(getOptions());
}
}
@Override
public void apply() throws ConfigurationException {
final CopyrightFileConfigManager copyrightFileConfigManager = myManager.getCopyrightFileConfigManager();
if (myFileType == null) {
copyrightFileConfigManager.setTemplateOptions(getOptions());
}
else {
copyrightFileConfigManager.setOptions(myFileType, getOptions());
}
}
@Override
public void reset() {
final CopyrightFileConfig options = myFileType == null
? myManager.getCopyrightFileConfigManager().getTemplateOptions()
: myManager.getCopyrightFileConfigManager().getOptions(myFileType);
boolean isBlock = options.isBlock();
if (isBlock) {
rbBlockComment.setSelected(true);
}
else {
rbLineComment.setSelected(true);
}
cbPrefixLines.setSelected(!myAllowBlock || options.isPrefixLines());
cbSeparatorAfter.setSelected(options.isSeparateAfter());
cbSeparatorBefore.setSelected(options.isSeparateBefore());
txtLengthBefore.setText(String.valueOf(options.getLenBefore()));
txtLengthAfter.setText(String.valueOf(options.getLenAfter()));
txtFiller.setText(options.getFiller() == CopyrightFileConfig.DEFAULT_FILLER ? "" : options.getFiller());
cbBox.setSelected(options.isBox());
final int fileTypeOverride = options.getFileTypeOverride();
myUseDefaultSettingsRadioButton.setSelected(fileTypeOverride == CopyrightFileConfig.USE_TEMPLATE);
myUseCustomFormattingOptionsRadioButton.setSelected(fileTypeOverride == CopyrightFileConfig.USE_TEXT);
myNoCopyright.setSelected(fileTypeOverride == CopyrightFileConfig.NO_COPYRIGHT);
if (options.isRelativeBefore()) {
rbBefore.setSelected(true);
}
else {
rbAfter.setSelected(true);
}
cbAddBlank.setSelected(options.isAddBlankAfter());
if (fileLocations != null) {
int choice = options.getFileLocation() - 1;
choice = Math.max(0, Math.min(choice, fileLocations.length - 1));
fileLocations[choice].setSelected(true);
}
updateOverride();
}
@Override
public void disposeUIResources() {
}
public void addOptionChangeListener(TemplateOptionsPanelListener listener) {
listeners.add(TemplateOptionsPanelListener.class, listener);
}
private void fireChangeEvent() {
Object[] fires = listeners.getListenerList();
for (int i = fires.length - 2; i >= 0; i -= 2) {
if (fires[i] == TemplateOptionsPanelListener.class) {
((TemplateOptionsPanelListener)fires[i + 1]).optionChanged();
}
}
}
@Override
@NotNull
public String getId() {
return getHelpTopic() + "." + myOptionName;
}
@Override
public Runnable enableSearch(String option) {
return null;
}
}