blob: c434c670823deae9265d0bf6c912132210950cb2 [file] [log] [blame]
/*
* Copyright 2000-2009 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.intellij.application.options;
import com.intellij.lang.Language;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighterFactory;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.DisplayPriority;
import com.intellij.psi.codeStyle.FileTypeIndentOptionsProvider;
import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
import com.intellij.ui.awt.RelativePoint;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class GeneralCodeStylePanel extends CodeStyleAbstractPanel {
@SuppressWarnings("UnusedDeclaration")
private static final Logger LOG = Logger.getInstance("#com.intellij.application.options.GeneralCodeStylePanel");
private static final String SYSTEM_DEPENDANT_STRING = ApplicationBundle.message("combobox.crlf.system.dependent");
private static final String UNIX_STRING = ApplicationBundle.message("combobox.crlf.unix");
private static final String WINDOWS_STRING = ApplicationBundle.message("combobox.crlf.windows");
private static final String MACINTOSH_STRING = ApplicationBundle.message("combobox.crlf.mac");
private JSpinner myRightMarginSpinner;
private JComboBox myLineSeparatorCombo;
private JPanel myPanel;
private JCheckBox myCbWrapWhenTypingReachesRightMargin;
private JPanel myDefaultIndentOptionsPanel;
private JCheckBox myEnableFormatterTags;
private JTextField myFormatterOnTagField;
private JTextField myFormatterOffTagField;
private JCheckBox myAcceptRegularExpressionsCheckBox;
private final SmartIndentOptionsEditor myIndentOptionsEditor;
public GeneralCodeStylePanel(CodeStyleSettings settings) {
super(settings);
final List<FileTypeIndentOptionsProvider> indentOptionsProviders =
Arrays.asList(Extensions.getExtensions(FileTypeIndentOptionsProvider.EP_NAME));
Collections.sort(indentOptionsProviders, new Comparator<FileTypeIndentOptionsProvider>() {
@Override
public int compare(FileTypeIndentOptionsProvider p1, FileTypeIndentOptionsProvider p2) {
Language lang1 = getLanguage(p1.getFileType());
if (lang1 == null) return -1;
Language lang2 = getLanguage(p2.getFileType());
if (lang2 == null) return 1;
DisplayPriority priority1 = LanguageCodeStyleSettingsProvider.getDisplayPriority(lang1);
DisplayPriority priority2 = LanguageCodeStyleSettingsProvider.getDisplayPriority(lang2);
if (priority1.equals(priority2)) {
return lang1.getDisplayName().compareTo(lang2.getDisplayName());
}
return priority1.compareTo(priority2);
}
});
myLineSeparatorCombo.addItem(SYSTEM_DEPENDANT_STRING);
myLineSeparatorCombo.addItem(UNIX_STRING);
myLineSeparatorCombo.addItem(WINDOWS_STRING);
myLineSeparatorCombo.addItem(MACINTOSH_STRING);
addPanelToWatch(myPanel);
myRightMarginSpinner.setModel(new SpinnerNumberModel(settings.RIGHT_MARGIN, 1, 1000000, 1));
myIndentOptionsEditor = new SmartIndentOptionsEditor();
myDefaultIndentOptionsPanel.add(myIndentOptionsEditor.createPanel(), BorderLayout.CENTER);
myEnableFormatterTags.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
boolean tagsEnabled = myEnableFormatterTags.isSelected();
myAcceptRegularExpressionsCheckBox.setEnabled(tagsEnabled);
myFormatterOnTagField.setEnabled(tagsEnabled);
myFormatterOffTagField.setEnabled(tagsEnabled);
}
});
}
@Nullable
private static Language getLanguage(FileType fileType) {
return (fileType instanceof LanguageFileType) ? ((LanguageFileType)fileType).getLanguage() : null;
}
@Override
protected void somethingChanged() {
super.somethingChanged();
}
@Override
protected int getRightMargin() {
return ((Number) myRightMarginSpinner.getValue()).intValue();
}
@Override
@NotNull
protected FileType getFileType() {
return FileTypes.PLAIN_TEXT;
}
@Override
protected String getPreviewText() {
return "";
}
@Override
public void apply(CodeStyleSettings settings) {
settings.LINE_SEPARATOR = getSelectedLineSeparator();
settings.RIGHT_MARGIN = ((Number) myRightMarginSpinner.getValue()).intValue();
settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = myCbWrapWhenTypingReachesRightMargin.isSelected();
myIndentOptionsEditor.setEnabled(true);
myIndentOptionsEditor.apply(settings, settings.OTHER_INDENT_OPTIONS);
settings.FORMATTER_TAGS_ENABLED = myEnableFormatterTags.isSelected();
settings.FORMATTER_TAGS_ACCEPT_REGEXP = myAcceptRegularExpressionsCheckBox.isSelected();
settings.FORMATTER_OFF_TAG = getTagText(myFormatterOffTagField, settings.FORMATTER_OFF_TAG);
settings.setFormatterOffPattern(compilePattern(settings, myFormatterOffTagField, settings.FORMATTER_OFF_TAG));
settings.FORMATTER_ON_TAG = getTagText(myFormatterOnTagField, settings.FORMATTER_ON_TAG);
settings.setFormatterOnPattern(compilePattern(settings, myFormatterOnTagField, settings.FORMATTER_ON_TAG));
}
@Nullable
private static Pattern compilePattern(CodeStyleSettings settings, JTextField field, String patternText) {
try {
return Pattern.compile(patternText);
}
catch (PatternSyntaxException pse) {
settings.FORMATTER_TAGS_ACCEPT_REGEXP = false;
showError(field, ApplicationBundle.message("settings.code.style.general.formatter.marker.invalid.regexp"));
return null;
}
}
private static String getTagText(JTextField field, String defualtValue) {
String fieldText = field.getText();
if (StringUtil.isEmpty(field.getText())) {
field.setText(defualtValue);
return defualtValue;
}
return fieldText;
}
@Nullable
private String getSelectedLineSeparator() {
if (UNIX_STRING.equals(myLineSeparatorCombo.getSelectedItem())) {
return "\n";
}
else if (MACINTOSH_STRING.equals(myLineSeparatorCombo.getSelectedItem())) {
return "\r";
}
else if (WINDOWS_STRING.equals(myLineSeparatorCombo.getSelectedItem())) {
return "\r\n";
}
return null;
}
@Override
public boolean isModified(CodeStyleSettings settings) {
if (!Comparing.equal(getSelectedLineSeparator(), settings.LINE_SEPARATOR)) {
return true;
}
if (settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN ^ myCbWrapWhenTypingReachesRightMargin.isSelected()) {
return true;
}
if (!Comparing.equal(myRightMarginSpinner.getValue(), settings.RIGHT_MARGIN)) return true;
myIndentOptionsEditor.setEnabled(true);
if (myEnableFormatterTags.isSelected()) {
if (
!settings.FORMATTER_TAGS_ENABLED ||
settings.FORMATTER_TAGS_ACCEPT_REGEXP != myAcceptRegularExpressionsCheckBox.isSelected() ||
!StringUtil.equals(myFormatterOffTagField.getText(), settings.FORMATTER_OFF_TAG) ||
!StringUtil.equals(myFormatterOnTagField.getText(), settings.FORMATTER_ON_TAG)) return true;
}
else {
if (settings.FORMATTER_TAGS_ENABLED) return true;
}
return myIndentOptionsEditor.isModified(settings, settings.OTHER_INDENT_OPTIONS);
}
@Override
public JComponent getPanel() {
return myPanel;
}
@Override
protected void resetImpl(final CodeStyleSettings settings) {
String lineSeparator = settings.LINE_SEPARATOR;
if ("\n".equals(lineSeparator)) {
myLineSeparatorCombo.setSelectedItem(UNIX_STRING);
}
else if ("\r\n".equals(lineSeparator)) {
myLineSeparatorCombo.setSelectedItem(WINDOWS_STRING);
}
else if ("\r".equals(lineSeparator)) {
myLineSeparatorCombo.setSelectedItem(MACINTOSH_STRING);
}
else {
myLineSeparatorCombo.setSelectedItem(SYSTEM_DEPENDANT_STRING);
}
myRightMarginSpinner.setValue(settings.RIGHT_MARGIN);
myCbWrapWhenTypingReachesRightMargin.setSelected(settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN);
myIndentOptionsEditor.reset(settings, settings.OTHER_INDENT_OPTIONS);
myIndentOptionsEditor.setEnabled(true);
myAcceptRegularExpressionsCheckBox.setSelected(settings.FORMATTER_TAGS_ACCEPT_REGEXP);
myAcceptRegularExpressionsCheckBox.setEnabled(settings.FORMATTER_TAGS_ENABLED);
myEnableFormatterTags.setSelected(settings.FORMATTER_TAGS_ENABLED);
myFormatterOnTagField.setText(settings.FORMATTER_ON_TAG);
myFormatterOnTagField.setEnabled(settings.FORMATTER_TAGS_ENABLED);
myFormatterOffTagField.setText(settings.FORMATTER_OFF_TAG);
myFormatterOffTagField.setEnabled(settings.FORMATTER_TAGS_ENABLED);
}
@Override
protected EditorHighlighter createHighlighter(final EditorColorsScheme scheme) {
//noinspection NullableProblems
return EditorHighlighterFactory.getInstance().createEditorHighlighter(getFileType(), scheme, null);
}
@Override
protected void prepareForReformat(final PsiFile psiFile) {
}
@Override
public Language getDefaultLanguage() {
return null;
}
private static void showError(final JTextField field, final String message) {
BalloonBuilder balloonBuilder = JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(message, MessageType.ERROR.getDefaultIcon(), MessageType.ERROR.getPopupBackground(), null);
balloonBuilder.setFadeoutTime(1500);
final Balloon balloon = balloonBuilder.createBalloon();
final Rectangle rect = field.getBounds();
final Point p = new Point(0, rect.height);
final RelativePoint point = new RelativePoint(field, p);
balloon.show(point, Balloon.Position.below);
Disposer.register(ProjectManager.getInstance().getDefaultProject(), balloon);
}
}