| package org.jetbrains.android.formatter; |
| |
| import com.intellij.application.options.CodeStyleAbstractPanel; |
| import com.intellij.ide.highlighter.XmlFileType; |
| import com.intellij.lang.xml.XMLLanguage; |
| import com.intellij.openapi.editor.colors.EditorColorsScheme; |
| import com.intellij.openapi.editor.highlighter.EditorHighlighter; |
| import com.intellij.openapi.fileTypes.FileType; |
| import com.intellij.openapi.ui.VerticalFlowLayout; |
| import com.intellij.psi.codeStyle.CodeStyleSettings; |
| import com.intellij.ui.IdeBorderFactory; |
| import com.intellij.ui.components.JBCheckBox; |
| import com.intellij.util.ui.UIUtil; |
| 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.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author Eugene.Kudelevsky |
| */ |
| public class AndroidXmlCodeStylePanel extends CodeStyleAbstractPanel { |
| private final JPanel myPanel; |
| private final JBCheckBox myUseCustomSettings; |
| private final List<MyFileSpecificPanel> myCodeStylePanels; |
| private final JPanel myFileSpecificCodeStylesPanel; |
| |
| AndroidXmlCodeStylePanel(CodeStyleSettings currentSettings, CodeStyleSettings settings) { |
| super(XMLLanguage.INSTANCE, currentSettings, settings); |
| myPanel = new JPanel(new BorderLayout()); |
| myPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); |
| JPanel centerPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); |
| myPanel.add(centerPanel, BorderLayout.CENTER); |
| myUseCustomSettings = new JBCheckBox("Use custom formatting settings for Android XML files"); |
| myPanel.add(myUseCustomSettings, BorderLayout.NORTH); |
| |
| myCodeStylePanels = new ArrayList<MyFileSpecificPanel>(); |
| |
| myCodeStylePanels.add(new ManifestCodeStylePanel()); |
| myCodeStylePanels.add(new LayoutCodeStylePanel()); |
| myCodeStylePanels.add(new ValueResourcesCodeStylePanel()); |
| myCodeStylePanels.add(new OtherCodeStylePanel()); |
| |
| myFileSpecificCodeStylesPanel = new JPanel(new GridLayout((myCodeStylePanels.size() + 1) / 2, 2, 15, 0)); |
| centerPanel.add(myFileSpecificCodeStylesPanel); |
| |
| myUseCustomSettings.addActionListener(new ActionListener() { |
| @Override |
| public void actionPerformed(ActionEvent e) { |
| UIUtil.setEnabled(myFileSpecificCodeStylesPanel, myUseCustomSettings.isSelected(), true); |
| } |
| }); |
| |
| for (MyFileSpecificPanel panel : myCodeStylePanels) { |
| final JPanel titledPanel = new JPanel(new BorderLayout()); |
| titledPanel.setBorder(IdeBorderFactory.createTitledBorder(panel.getTitle())); |
| titledPanel.add(panel, BorderLayout.CENTER); |
| myFileSpecificCodeStylesPanel.add(titledPanel); |
| } |
| } |
| |
| @Override |
| protected int getRightMargin() { |
| return 0; |
| } |
| |
| @Nullable |
| @Override |
| protected EditorHighlighter createHighlighter(EditorColorsScheme scheme) { |
| return null; |
| } |
| |
| @NotNull |
| @Override |
| protected FileType getFileType() { |
| return XmlFileType.INSTANCE; |
| } |
| |
| @Nullable |
| @Override |
| protected String getPreviewText() { |
| return null; |
| } |
| |
| @Override |
| public void apply(CodeStyleSettings settings) { |
| final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings); |
| androidSettings.USE_CUSTOM_SETTINGS = myUseCustomSettings.isSelected(); |
| |
| for (MyFileSpecificPanel panel : myCodeStylePanels) { |
| panel.apply(androidSettings); |
| } |
| } |
| |
| @Override |
| public boolean isModified(CodeStyleSettings settings) { |
| final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings); |
| |
| if (androidSettings.USE_CUSTOM_SETTINGS != myUseCustomSettings.isSelected()) { |
| return true; |
| } |
| |
| for (MyFileSpecificPanel panel : myCodeStylePanels) { |
| if (panel.isModified(androidSettings)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Nullable |
| @Override |
| public JComponent getPanel() { |
| return myPanel; |
| } |
| |
| @Override |
| protected void resetImpl(CodeStyleSettings settings) { |
| final AndroidXmlCodeStyleSettings androidSettings = AndroidXmlCodeStyleSettings.getInstance(settings); |
| myUseCustomSettings.setSelected(androidSettings.USE_CUSTOM_SETTINGS); |
| UIUtil.setEnabled(myFileSpecificCodeStylesPanel, androidSettings.USE_CUSTOM_SETTINGS, true); |
| |
| for (MyFileSpecificPanel panel : myCodeStylePanels) { |
| panel.resetImpl(androidSettings); |
| } |
| } |
| |
| public abstract static class MyFileSpecificPanel<T extends AndroidXmlCodeStyleSettings.MySettings> extends JPanel { |
| private JPanel myPanel; |
| private JPanel myAdditionalOptionsPanel; |
| private JComboBox myWrapAttributesCombo; |
| |
| protected JBCheckBox myInsertLineBreakBeforeFirstAttributeCheckBox; |
| protected JBCheckBox myInsertLineBreakAfterLastAttributeCheckbox; |
| |
| private final String myTitle; |
| private final ContextSpecificSettingsProviders.Provider<T> mySettingsProvider; |
| |
| protected MyFileSpecificPanel(String title, ContextSpecificSettingsProviders.Provider<T> provider) { |
| myTitle = title; |
| mySettingsProvider = provider; |
| } |
| |
| protected void init() { |
| final JPanel panel = getAdditionalOptionsPanel(); |
| |
| if (panel != null) { |
| myAdditionalOptionsPanel.add(panel, BorderLayout.CENTER); |
| } |
| else { |
| myAdditionalOptionsPanel.setVisible(false); |
| } |
| setLayout(new BorderLayout()); |
| add(myPanel, BorderLayout.CENTER); |
| |
| fillWrappingCombo(myWrapAttributesCombo); |
| } |
| |
| @Nullable |
| public JPanel getAdditionalOptionsPanel() { |
| return null; |
| } |
| |
| public final void apply(AndroidXmlCodeStyleSettings settings) { |
| apply(mySettingsProvider.getSettings(settings)); |
| } |
| |
| protected void apply(T s) { |
| s.WRAP_ATTRIBUTES = ourWrappings[myWrapAttributesCombo.getSelectedIndex()]; |
| s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE = myInsertLineBreakBeforeFirstAttributeCheckBox.isSelected(); |
| s.INSERT_LINE_BREAK_AFTER_LAST_ATTRIBUTE = myInsertLineBreakAfterLastAttributeCheckbox.isSelected(); |
| } |
| |
| public final boolean isModified(AndroidXmlCodeStyleSettings settings) { |
| return isModified(mySettingsProvider.getSettings(settings)); |
| } |
| |
| protected boolean isModified(T s) { |
| if (s.WRAP_ATTRIBUTES != ourWrappings[myWrapAttributesCombo.getSelectedIndex()]) { |
| return true; |
| } |
| if (s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE != myInsertLineBreakBeforeFirstAttributeCheckBox.isSelected()) { |
| return true; |
| } |
| if (s.INSERT_LINE_BREAK_AFTER_LAST_ATTRIBUTE != myInsertLineBreakAfterLastAttributeCheckbox.isSelected()) { |
| return true; |
| } |
| return false; |
| } |
| |
| protected final void resetImpl(AndroidXmlCodeStyleSettings settings) { |
| resetImpl(mySettingsProvider.getSettings(settings)); |
| } |
| |
| protected void resetImpl(T s) { |
| myWrapAttributesCombo.setSelectedIndex(getIndexForWrapping(s.WRAP_ATTRIBUTES)); |
| myInsertLineBreakBeforeFirstAttributeCheckBox.setSelected(s.INSERT_LINE_BREAK_BEFORE_FIRST_ATTRIBUTE); |
| myInsertLineBreakAfterLastAttributeCheckbox.setSelected(s.INSERT_LINE_BREAK_AFTER_LAST_ATTRIBUTE); |
| } |
| |
| @NotNull |
| public String getTitle() { |
| return myTitle; |
| } |
| } |
| |
| private static class LayoutCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.LayoutSettings> { |
| private JPanel myPanel; |
| private JBCheckBox myInsertNewLineBeforeTagCheckBox; |
| |
| public LayoutCodeStylePanel() { |
| super("Layout Files", ContextSpecificSettingsProviders.LAYOUT); |
| init(); |
| } |
| |
| @Nullable |
| @Override |
| public JPanel getAdditionalOptionsPanel() { |
| return myPanel; |
| } |
| |
| @Override |
| protected boolean isModified(AndroidXmlCodeStyleSettings.LayoutSettings s) { |
| if (super.isModified(s)) { |
| return true; |
| } |
| return myInsertNewLineBeforeTagCheckBox.isSelected() != s.INSERT_BLANK_LINE_BEFORE_TAG; |
| } |
| |
| @Override |
| protected void resetImpl(AndroidXmlCodeStyleSettings.LayoutSettings s) { |
| super.resetImpl(s); |
| myInsertNewLineBeforeTagCheckBox.setSelected(s.INSERT_BLANK_LINE_BEFORE_TAG); |
| } |
| |
| @Override |
| protected void apply(AndroidXmlCodeStyleSettings.LayoutSettings s) { |
| super.apply(s); |
| s.INSERT_BLANK_LINE_BEFORE_TAG = myInsertNewLineBeforeTagCheckBox.isSelected(); |
| } |
| } |
| |
| public static class ManifestCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.ManifestSettings> { |
| private final JBCheckBox myGroupTagsCheckBox; |
| private JPanel myPanel; |
| |
| public ManifestCodeStylePanel() { |
| super("AndroidManifest.xml", ContextSpecificSettingsProviders.MANIFEST); |
| |
| myPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); |
| myGroupTagsCheckBox = new JBCheckBox("Group tags with the same name"); |
| myPanel.add(myGroupTagsCheckBox); |
| |
| init(); |
| } |
| |
| @Nullable |
| @Override |
| public JPanel getAdditionalOptionsPanel() { |
| return myPanel; |
| } |
| |
| @Override |
| protected void apply(AndroidXmlCodeStyleSettings.ManifestSettings s) { |
| super.apply(s); |
| s.GROUP_TAGS_WITH_SAME_NAME = myGroupTagsCheckBox.isSelected(); |
| } |
| |
| @Override |
| protected boolean isModified(AndroidXmlCodeStyleSettings.ManifestSettings s) { |
| if (super.isModified(s)) { |
| return true; |
| } |
| return s.GROUP_TAGS_WITH_SAME_NAME != myGroupTagsCheckBox.isSelected(); |
| } |
| |
| @Override |
| protected void resetImpl(AndroidXmlCodeStyleSettings.ManifestSettings s) { |
| super.resetImpl(s); |
| myGroupTagsCheckBox.setSelected(s.GROUP_TAGS_WITH_SAME_NAME); |
| } |
| } |
| |
| public static class ValueResourcesCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.ValueResourceFileSettings> { |
| private final JBCheckBox myInsertLineBreaksAroundStyleCheckBox; |
| private JPanel myPanel; |
| |
| public ValueResourcesCodeStylePanel() { |
| super("Value Resource Files and Selectors", ContextSpecificSettingsProviders.VALUE_RESOURCE_FILE); |
| myPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 0, 0, true, false)); |
| myInsertLineBreaksAroundStyleCheckBox = new JBCheckBox("Insert line breaks around style declaration"); |
| myPanel.add(myInsertLineBreaksAroundStyleCheckBox); |
| |
| init(); |
| myInsertLineBreakBeforeFirstAttributeCheckBox.setVisible(false); |
| myInsertLineBreakAfterLastAttributeCheckbox.setVisible(false); |
| } |
| |
| @Nullable |
| @Override |
| public JPanel getAdditionalOptionsPanel() { |
| return myPanel; |
| } |
| |
| @Override |
| protected void apply(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) { |
| super.apply(s); |
| s.INSERT_LINE_BREAKS_AROUND_STYLE = myInsertLineBreaksAroundStyleCheckBox.isSelected(); |
| } |
| |
| @Override |
| protected boolean isModified(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) { |
| if (super.isModified(s)) { |
| return true; |
| } |
| return s.INSERT_LINE_BREAKS_AROUND_STYLE != myInsertLineBreaksAroundStyleCheckBox.isSelected(); |
| } |
| |
| @Override |
| protected void resetImpl(AndroidXmlCodeStyleSettings.ValueResourceFileSettings s) { |
| super.resetImpl(s); |
| myInsertLineBreaksAroundStyleCheckBox.setSelected(s.INSERT_LINE_BREAKS_AROUND_STYLE); |
| } |
| } |
| |
| public static class OtherCodeStylePanel extends MyFileSpecificPanel<AndroidXmlCodeStyleSettings.OtherSettings> { |
| public OtherCodeStylePanel() { |
| super("Other XML resource files", ContextSpecificSettingsProviders.OTHER); |
| init(); |
| } |
| } |
| } |