From 9426c5a07524e0dcff0884f76cf28a683d5374da Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Tue, 13 Jan 2015 11:07:35 +0300 Subject: [PATCH 1/6] remove a flag to disable multiple carets in editor and supporting legacy code missed cleanup --- .../completion/JavaAutoPopupTest.groovy | 36 ------------------- 1 file changed, 36 deletions(-) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy index e2e9a3c99eef..5635e5418ea0 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy @@ -1226,42 +1226,6 @@ public class Test { assert !lookup } - public void testBlockSelection() { - doTestBlockSelection """ -class Foo {{ - tx; - tx; -}}""", '\n', ''' -class Foo {{ - toString()x; - toString()x; -}}''' - } - - public void testBlockSelectionTab() { - doTestBlockSelection """ -class Foo {{ - tx; - tx; -}}""", '\t', ''' -class Foo {{ - toString(); - toString(); -}}''' - } - - public void testBlockSelectionBackspace() { - doTestBlockSelection """ -class Foo {{ - t; - t; -}}""", '\b\t', ''' -class Foo {{ - toString(); - toString(); -}}''' - } - public void testMulticaret() { doTestMulticaret """ class Foo {{ From cf9e33f6af1532a08edf36cd7319b614802d75cb Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 12 Jan 2015 18:07:52 +0300 Subject: [PATCH 2/6] Ensure file is writable while updating tag --- .../template/emmet/EmmetUpdateTagAction.java | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetUpdateTagAction.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetUpdateTagAction.java index aca377454b75..95b1f761eb9d 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetUpdateTagAction.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/EmmetUpdateTagAction.java @@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.ReadonlyStatusHandler; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.util.PsiTreeUtil; @@ -170,32 +171,34 @@ public class EmmetUpdateTagAction extends BaseCodeInsightAction implements DumbA @Override protected void run(@NotNull Result result) throws Throwable { if (tag.isValid()) { - tag.setAttribute(HtmlUtil.CLASS_ATTRIBUTE_NAME, StringUtil.join(classes, " ").trim()); + if (!ReadonlyStatusHandler.getInstance(file.getProject()).ensureFilesWritable(file.getVirtualFile()).hasReadonlyFiles()) { + tag.setAttribute(HtmlUtil.CLASS_ATTRIBUTE_NAME, StringUtil.join(classes, " ").trim()); - for (Map.Entry attribute : attributes.entrySet()) { - final String attributeName = attribute.getKey(); - if (StringUtil.startsWithChar(attributeName, '+')) { - final XmlAttribute existingAttribute = tag.getAttribute(attributeName.substring(1)); - if (existingAttribute != null) { - existingAttribute.setValue(StringUtil.notNullize(existingAttribute.getValue() + attribute.getValue())); + for (Map.Entry attribute : attributes.entrySet()) { + final String attributeName = attribute.getKey(); + if (StringUtil.startsWithChar(attributeName, '+')) { + final XmlAttribute existingAttribute = tag.getAttribute(attributeName.substring(1)); + if (existingAttribute != null) { + existingAttribute.setValue(StringUtil.notNullize(existingAttribute.getValue() + attribute.getValue())); + } + else { + tag.setAttribute(attributeName.substring(1), attribute.getValue()); + } + } + else if (StringUtil.startsWithChar(attributeName, '-')) { + final XmlAttribute existingAttribute = tag.getAttribute(attributeName.substring(1)); + if (existingAttribute != null) { + existingAttribute.delete(); + } } else { - tag.setAttribute(attributeName.substring(1), attribute.getValue()); + tag.setAttribute(attributeName, attribute.getValue()); } } - else if (StringUtil.startsWithChar(attributeName, '-')) { - final XmlAttribute existingAttribute = tag.getAttribute(attributeName.substring(1)); - if (existingAttribute != null) { - existingAttribute.delete(); - } - } - else { - tag.setAttribute(attributeName, attribute.getValue()); - } - } - if (newTagName != null) { - tag.setName(newTagName); + if (newTagName != null) { + tag.setName(newTagName); + } } } } From fca058c4fc1ad78ce7349473396a607c2713c676 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 12 Jan 2015 20:30:47 +0300 Subject: [PATCH 3/6] Refactor Emmet configurable - separate generator-specific configurables - disable particular emmet generator via lookupAction - show particular emmet generator configurable via lookupAction --- .../src/META-INF/XmlPlugin.xml | 3 +- .../emmet/EmmetCompositeConfigurable.java | 78 +++++++++++-------- .../emmet/EmmetConfigurableProvider.java | 23 ++++-- .../options/emmet/XmlEmmetConfigurable.form | 73 +++++++---------- .../options/emmet/XmlEmmetConfigurable.java | 16 +++- .../completion/EmmetLookupActionProvider.java | 69 +++++++++------- .../generators/XmlZenCodingGenerator.java | 6 ++ .../generators/XmlZenCodingGeneratorImpl.java | 4 +- .../emmet/generators/ZenCodingGenerator.java | 7 +- 9 files changed, 162 insertions(+), 117 deletions(-) diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index f3c170e5c191..c988a7818ee3 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -196,7 +196,8 @@ - + diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetCompositeConfigurable.java b/xml/impl/src/com/intellij/application/options/emmet/EmmetCompositeConfigurable.java index 29465ed2a34b..e9daf6c45caa 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/EmmetCompositeConfigurable.java +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetCompositeConfigurable.java @@ -15,16 +15,13 @@ */ package com.intellij.application.options.emmet; -import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGenerator; -import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.codeInsight.template.impl.TemplateExpandShortcutPanel; -import com.intellij.openapi.options.CompositeConfigurable; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.uiDesigner.core.GridConstraints; import com.intellij.uiDesigner.core.GridLayoutManager; -import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -32,12 +29,21 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; -import java.util.List; +import java.util.Collection; +import java.util.Collections; -public class EmmetCompositeConfigurable extends CompositeConfigurable implements SearchableConfigurable { +public class EmmetCompositeConfigurable extends SearchableConfigurable.Parent.Abstract { + private final Configurable[] myNestedConfigurables; + @NotNull private final Configurable[] myInnerConfigurables; private TemplateExpandShortcutPanel myTemplateExpandShortcutPanel; + + public EmmetCompositeConfigurable(@NotNull Configurable... innerConfigurables) { + this(Collections.emptyList(), innerConfigurables); + } - public EmmetCompositeConfigurable() { + public EmmetCompositeConfigurable(Collection nestedConfigurables, @NotNull Configurable... innerConfigurables) { + myNestedConfigurables = nestedConfigurables.toArray(new Configurable[nestedConfigurables.size()]); + myInnerConfigurables = innerConfigurables; myTemplateExpandShortcutPanel = new TemplateExpandShortcutPanel(XmlBundle.message("emmet.expand.abbreviation.with")); } @@ -55,20 +61,19 @@ public class EmmetCompositeConfigurable extends CompositeConfigurable configurables = getConfigurables(); - final JPanel rootPanel = new JPanel(new GridLayoutManager(configurables.size() + 1, 1, new Insets(0, 0, 0, 0), -1, -1, false, false)); + public JComponent createComponent() { + final JPanel rootPanel = new JPanel(new GridLayoutManager(myInnerConfigurables.length + 1, 1, new Insets(0, 0, 0, 0), -1, -1, false, false)); rootPanel.add(myTemplateExpandShortcutPanel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTH, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_CAN_SHRINK, GridConstraints.SIZEPOLICY_FIXED, null, null, null)); - for (int i = 0; i < configurables.size(); i++) { - UnnamedConfigurable configurable = configurables.get(i); + for (int i = 0; i < myInnerConfigurables.length; i++) { + UnnamedConfigurable configurable = myInnerConfigurables[i]; final JComponent component = configurable.createComponent(); assert component != null; int vSizePolicy = GridConstraints.SIZEPOLICY_CAN_GROW | GridConstraints.SIZEPOLICY_CAN_SHRINK; - if (i + 1 == configurables.size()) { + if (i + 1 == myInnerConfigurables.length) { vSizePolicy |= GridConstraints.SIZEPOLICY_WANT_GROW; } rootPanel.add(component, new GridConstraints(i + 1, 0, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_BOTH, @@ -82,21 +87,33 @@ public class EmmetCompositeConfigurable extends CompositeConfigurable createConfigurables() { - List xmlConfigurables = ContainerUtil.newSmartList(); - List configurables = ContainerUtil.newSmartList(); - for (ZenCodingGenerator zenCodingGenerator : ZenCodingGenerator.getInstances()) { - if (zenCodingGenerator instanceof XmlZenCodingGenerator) { - ContainerUtil.addIfNotNull(xmlConfigurables, zenCodingGenerator.createConfigurable()); - } - else { - ContainerUtil.addIfNotNull(configurables, zenCodingGenerator.createConfigurable()); - } - } - return ContainerUtil.concat(xmlConfigurables, configurables); - } - @NotNull @Override public String getId() { return "reference.idesettings.emmet"; } + @Override + public boolean hasOwnContent() { + return true; + } + @Nullable @Override public Runnable enableSearch(String option) { return null; } + + @Override + protected Configurable[] buildConfigurables() { + return myNestedConfigurables; + } } diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java index 6128439c4ee2..c857e9843aec 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java @@ -15,18 +15,31 @@ */ package com.intellij.application.options.emmet; +import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurableProvider; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -/** - * User: zolotov - * Date: 2/20/13 - */ +import java.util.List; + public class EmmetConfigurableProvider extends ConfigurableProvider { @Nullable @Override public Configurable createConfigurable() { - return new EmmetCompositeConfigurable(); + final List availableConfigurables = getAvailableConfigurables(); + return availableConfigurables.size() == 1 + ? new EmmetCompositeConfigurable(ContainerUtil.getFirstItem(availableConfigurables)) + : new EmmetCompositeConfigurable(availableConfigurables); + } + + @NotNull + public static List getAvailableConfigurables() { + List configurables = ContainerUtil.newSmartList(); + for (ZenCodingGenerator zenCodingGenerator : ZenCodingGenerator.getInstances()) { + ContainerUtil.addIfNotNull(configurables, zenCodingGenerator.createConfigurable()); + } + return configurables; } } diff --git a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form index a69d1291ab70..fc8ae107c270 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form +++ b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form @@ -1,6 +1,6 @@
- + @@ -8,59 +8,46 @@ - + + + + + + + + + + + + + + + + + - + - - - - + - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - + + + + + + + + diff --git a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java index 779cf418147c..7e79a9ad6be3 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java +++ b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java @@ -19,13 +19,13 @@ import com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter; import com.intellij.openapi.Disposable; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; -import com.intellij.openapi.options.UnnamedConfigurable; import com.intellij.ui.CheckBoxList; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.components.JBCheckBox; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.XmlBundle; +import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -34,7 +34,7 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Set; -public class XmlEmmetConfigurable implements UnnamedConfigurable, Disposable, Configurable.NoScroll { +public class XmlEmmetConfigurable implements Configurable, Disposable, Configurable.NoScroll { private JPanel myPanel; private JBCheckBox myEnableEmmetJBCheckBox; private JBCheckBox myEnablePreviewJBCheckBox; @@ -119,4 +119,16 @@ public class XmlEmmetConfigurable implements UnnamedConfigurable, Disposable, Co } return result; } + + @Nls + @Override + public String getDisplayName() { + return "XML"; + } + + @Nullable + @Override + public String getHelpTopic() { + return XmlBundle.message("emmet.configuration.title"); + } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java index a127ab226f7c..3c9d15e25cda 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java @@ -16,17 +16,20 @@ package com.intellij.codeInsight.template.emmet.completion; import com.intellij.application.options.emmet.EmmetCompositeConfigurable; -import com.intellij.application.options.emmet.EmmetOptions; +import com.intellij.application.options.emmet.XmlEmmetConfigurable; import com.intellij.codeInsight.lookup.Lookup; import com.intellij.codeInsight.lookup.LookupActionProvider; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementAction; import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; +import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement; import com.intellij.icons.AllIcons; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ShowSettingsUtil; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiElement; import com.intellij.util.Consumer; import com.intellij.util.PlatformIcons; @@ -35,36 +38,44 @@ public class EmmetLookupActionProvider implements LookupActionProvider { public void fillActions(LookupElement element, final Lookup lookup, Consumer consumer) { if (element instanceof CustomLiveTemplateLookupElement && ((CustomLiveTemplateLookupElement)element).getCustomLiveTemplate() instanceof ZenCodingTemplate) { - consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit Emmet settings") { - @Override - public Result performLookupAction() { - final Project project = lookup.getEditor().getProject(); - assert project != null; - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - if (project.isDisposed()) return; - final EmmetCompositeConfigurable configurable = new EmmetCompositeConfigurable(); - ShowSettingsUtil.getInstance().editConfigurable(project, configurable); - } - }); - return Result.HIDE_LOOKUP; - } - }); + final PsiElement context = lookup.getPsiElement(); + final ZenCodingGenerator generator = context != null ? ZenCodingTemplate.findApplicableDefaultGenerator(context, false) : null; + if (generator != null) { + consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit Emmet settings") { + @Override + public Result performLookupAction() { + final Project project = lookup.getEditor().getProject(); + assert project != null; + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + if (project.isDisposed()) return; - consumer.consume(new LookupElementAction(AllIcons.Actions.Delete, String.format("Disable Emmet")) { - @Override - public Result performLookupAction() { - ApplicationManager.getApplication().invokeLater(new Runnable() { - @Override - public void run() { - EmmetOptions.getInstance().setEmmetEnabled(false); - } - }); - return Result.HIDE_LOOKUP; - } - }); + final Configurable generatorSpecificConfigurable = generator.createConfigurable(); + EmmetCompositeConfigurable configurable = generatorSpecificConfigurable != null + ? new EmmetCompositeConfigurable(generatorSpecificConfigurable) + : new EmmetCompositeConfigurable(new XmlEmmetConfigurable()); + ShowSettingsUtil.getInstance().editConfigurable(project, configurable); + } + }); + return Result.HIDE_LOOKUP; + } + }); + + consumer.consume(new LookupElementAction(AllIcons.Actions.Delete, "Disable Emmet") { + @Override + public Result performLookupAction() { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + generator.disableEmmet(); + } + }); + return Result.HIDE_LOOKUP; + } + }); + } } } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java index 97d02cd080be..0434ea054e07 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGenerator.java @@ -15,6 +15,7 @@ */ package com.intellij.codeInsight.template.emmet.generators; +import com.intellij.application.options.emmet.EmmetOptions; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.emmet.ZenCodingTemplate; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; @@ -118,4 +119,9 @@ public abstract class XmlZenCodingGenerator extends ZenCodingGenerator { String key = computeKey(documentText.subSequence(startOffset, currentOffset)); return !StringUtil.isEmpty(key) && ZenCodingTemplate.checkTemplateKey(key, callback, this) ? key : null; } + + @Override + public void disableEmmet() { + EmmetOptions.getInstance().setEmmetEnabled(false); + } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGeneratorImpl.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGeneratorImpl.java index 7332255505d7..d74ccf9b7274 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGeneratorImpl.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/XmlZenCodingGeneratorImpl.java @@ -27,7 +27,7 @@ import com.intellij.openapi.editor.Document; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.StdFileTypes; -import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; @@ -154,7 +154,7 @@ public class XmlZenCodingGeneratorImpl extends XmlZenCodingGenerator { @Nullable @Override - public UnnamedConfigurable createConfigurable() { + public Configurable createConfigurable() { return new XmlEmmetConfigurable(); } } diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java index 6b2f2c60ae71..e333a0f1bc29 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/generators/ZenCodingGenerator.java @@ -24,7 +24,7 @@ import com.intellij.codeInsight.template.emmet.tokens.ZenCodingToken; import com.intellij.codeInsight.template.impl.TemplateImpl; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.openapi.options.UnnamedConfigurable; +import com.intellij.openapi.options.Configurable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; @@ -140,11 +140,14 @@ public abstract class ZenCodingGenerator { } @Nullable - public UnnamedConfigurable createConfigurable() { + public Configurable createConfigurable() { return null; } public boolean hasCompletionItem() { return false; } + + public void disableEmmet() { + } } From b27b1022a94364dc3276bb0aca700941e299d2db Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Mon, 12 Jan 2015 21:35:08 +0300 Subject: [PATCH 4/6] Reimplement emmet filters list with checkboxes --- .../options/emmet/XmlEmmetConfigurable.form | 9 +--- .../options/emmet/XmlEmmetConfigurable.java | 47 +++++++++++++------ 2 files changed, 33 insertions(+), 23 deletions(-) diff --git a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form index fc8ae107c270..dbb1daca8c19 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form +++ b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.form @@ -31,14 +31,7 @@ - - - - - - - - +
diff --git a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java index 7e79a9ad6be3..736a28c3067c 100644 --- a/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java +++ b/xml/impl/src/com/intellij/application/options/emmet/XmlEmmetConfigurable.java @@ -19,10 +19,8 @@ import com.intellij.codeInsight.template.emmet.filters.ZenCodingFilter; import com.intellij.openapi.Disposable; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; -import com.intellij.ui.CheckBoxList; import com.intellij.ui.IdeBorderFactory; import com.intellij.ui.components.JBCheckBox; -import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.Nls; @@ -30,35 +28,50 @@ 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.List; +import java.util.Map; import java.util.Set; public class XmlEmmetConfigurable implements Configurable, Disposable, Configurable.NoScroll { private JPanel myPanel; private JBCheckBox myEnableEmmetJBCheckBox; private JBCheckBox myEnablePreviewJBCheckBox; - private CheckBoxList myFiltersCheckBoxList; private JPanel myFiltersListPanel; private JBCheckBox myEnableHrefAutodetectJBCheckBox; + private Map myFilterCheckboxes = ContainerUtil.newHashMap(); + public XmlEmmetConfigurable() { myEnableEmmetJBCheckBox.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { boolean selected = myEnableEmmetJBCheckBox.isSelected(); myEnablePreviewJBCheckBox.setEnabled(selected); - myFiltersCheckBoxList.setEnabled(selected); + myFiltersListPanel.setEnabled(selected); myEnableHrefAutodetectJBCheckBox.setEnabled(selected); } }); - myFiltersListPanel.setBorder(IdeBorderFactory.createTitledBorder(XmlBundle.message("emmet.filters.enabled.by.default"), false)); - myFiltersCheckBoxList.setItems(ZenCodingFilter.getInstances(), new Function() { - @Override - public String fun(ZenCodingFilter filter) { - return filter.getDisplayName(); - } - }); + myFiltersListPanel.setBorder(IdeBorderFactory.createTitledBorder(XmlBundle.message("emmet.filters.enabled.by.default"))); + createFiltersCheckboxes(); + } + + public void createFiltersCheckboxes() { + final List filters = ZenCodingFilter.getInstances(); + final GridBagLayout layoutManager = new GridBagLayout(); + final GridBagConstraints constraints = new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, + new Insets(0, 0, 0, 0), 0, 0); + myFiltersListPanel.setLayout(layoutManager); + for (int i = 0; i < filters.size(); i++) { + ZenCodingFilter filter = filters.get(i); + final JBCheckBox checkBox = new JBCheckBox(filter.getDisplayName()); + myFilterCheckboxes.put(filter.getSuffix(), checkBox); + constraints.gridy = i; + myFiltersListPanel.add(checkBox, constraints); + } + myFiltersListPanel.revalidate(); } @Override @@ -101,7 +114,11 @@ public class XmlEmmetConfigurable implements Configurable, Disposable, Configura Set enabledByDefault = emmetOptions.getFiltersEnabledByDefault(); for (ZenCodingFilter filter : ZenCodingFilter.getInstances()) { - myFiltersCheckBoxList.setItemSelected(filter, enabledByDefault.contains(filter.getSuffix())); + final String filterSuffix = filter.getSuffix(); + final JBCheckBox checkBox = myFilterCheckboxes.get(filterSuffix); + if (checkBox != null) { + checkBox.setSelected(enabledByDefault.contains(filterSuffix)); + } } } @@ -112,9 +129,9 @@ public class XmlEmmetConfigurable implements Configurable, Disposable, Configura @NotNull private Set enabledFilters() { Set result = ContainerUtil.newHashSet(); - for (ZenCodingFilter filter : ZenCodingFilter.getInstances()) { - if (myFiltersCheckBoxList.isItemSelected(filter)) { - result.add(filter.getSuffix()); + for (Map.Entry checkbox : myFilterCheckboxes.entrySet()) { + if (checkbox.getValue().isSelected()) { + result.add(checkbox.getKey()); } } return result; From 137a168223cef71dc87f58f40296147f29d5e6a3 Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Tue, 13 Jan 2015 11:16:26 +0300 Subject: [PATCH 5/6] Do not rely on standard html file type while generating Emmet template --- .../codeInsight/template/emmet/nodes/GenerationNode.java | 5 +++-- .../codeInsight/template/emmet/tokens/TemplateToken.java | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java index b88a54d9551a..4dffc3bc84c6 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/nodes/GenerationNode.java @@ -28,6 +28,7 @@ import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGeneratorI import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator; import com.intellij.codeInsight.template.emmet.tokens.TemplateToken; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.ide.highlighter.HtmlFileType; import com.intellij.injected.editor.DocumentWindowImpl; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.command.undo.UndoConstants; @@ -281,7 +282,7 @@ public class GenerationNode extends UserDataHolderBase { final XmlFile xmlFile = token.getFile(); PsiFileFactory fileFactory = PsiFileFactory.getInstance(xmlFile.getProject()); - XmlFile dummyFile = (XmlFile)fileFactory.createFileFromText("dummy.html", StdFileTypes.HTML, xmlFile.getText()); + XmlFile dummyFile = (XmlFile)fileFactory.createFileFromText("dummy.html", HtmlFileType.INSTANCE, xmlFile.getText()); final XmlTag tag = dummyFile.getRootTag(); if (tag != null) { @@ -307,7 +308,7 @@ public class GenerationNode extends UserDataHolderBase { } XmlTag tag1 = hasChildren ? expandEmptyTagIfNecessary(tag) : tag; setAttributeValues(tag1, attributes, callback); - XmlFile physicalFile = (XmlFile)fileFactory.createFileFromText("dummy.html", StdFileTypes.HTML, tag1.getContainingFile().getText(), + XmlFile physicalFile = (XmlFile)fileFactory.createFileFromText("dummy.html", HtmlFileType.INSTANCE, tag1.getContainingFile().getText(), LocalTimeCounter.currentTime(), true); VirtualFile vFile = physicalFile.getVirtualFile(); if (vFile != null) { diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java index 6cd755f84c47..f1d5907ae1b0 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/tokens/TemplateToken.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.template.emmet.tokens; import com.intellij.codeInsight.template.CustomTemplateCallback; import com.intellij.codeInsight.template.emmet.XmlEmmetParser; import com.intellij.codeInsight.template.impl.TemplateImpl; +import com.intellij.ide.highlighter.HtmlFileType; import com.intellij.openapi.command.undo.UndoConstants; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.vfs.VirtualFile; @@ -99,7 +100,7 @@ public class TemplateToken extends ZenCodingToken { String templateString = template.getString(); final PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(callback.getProject()); if (!containsAttrsVar(template)) { - XmlFile dummyFile = (XmlFile)psiFileFactory.createFileFromText("dummy.xml", StdFileTypes.HTML, templateString); + XmlFile dummyFile = (XmlFile)psiFileFactory.createFileFromText("dummy.xml", HtmlFileType.INSTANCE, templateString); dummyRootTag = dummyFile.getRootTag(); if (dummyRootTag != null) { addMissingAttributes(dummyRootTag, attributes); From 8b17c6e80dbc4c20bff0af4b87da985140d6951b Mon Sep 17 00:00:00 2001 From: Dennis Ushakov Date: Tue, 13 Jan 2015 12:12:51 +0300 Subject: [PATCH 6/6] replace annotator with editor notification --- plugins/editorconfig/src/META-INF/plugin.xml | 1 + .../annotations/EditorConfigAnnotator.java | 127 ------------------ .../EditorConfigNotifierProvider.java | 70 ++++++++++ .../SettingsProviderComponent.java | 25 +--- 4 files changed, 72 insertions(+), 151 deletions(-) delete mode 100644 plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java create mode 100644 plugins/editorconfig/src/org/editorconfig/plugincomponents/EditorConfigNotifierProvider.java diff --git a/plugins/editorconfig/src/META-INF/plugin.xml b/plugins/editorconfig/src/META-INF/plugin.xml index 06915d66114b..2e52170a3434 100644 --- a/plugins/editorconfig/src/META-INF/plugin.xml +++ b/plugins/editorconfig/src/META-INF/plugin.xml @@ -18,6 +18,7 @@ + diff --git a/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java b/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java deleted file mode 100644 index 729ecf4e7a60..000000000000 --- a/plugins/editorconfig/src/org/editorconfig/annotations/EditorConfigAnnotator.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.editorconfig.annotations; - -import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.ide.util.PropertiesComponent; -import com.intellij.injected.editor.VirtualFileWindow; -import com.intellij.lang.annotation.Annotation; -import com.intellij.lang.annotation.AnnotationHolder; -import com.intellij.lang.annotation.Annotator; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.markup.GutterIconRenderer; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.util.IncorrectOperationException; -import com.intellij.util.ObjectUtils; -import icons.EditorconfigIcons; -import org.editorconfig.Utils; -import org.editorconfig.core.EditorConfig; -import org.editorconfig.plugincomponents.SettingsProviderComponent; -import org.editorconfig.settings.EditorConfigSettings; -import org.jetbrains.annotations.NotNull; - -import javax.swing.*; -import java.util.List; - -/** - * @author Dennis.Ushakov - */ -public class EditorConfigAnnotator implements Annotator { - private static final String EDITOR_CONFIG_ACCEPTED = "editor.config.accepted"; - - @Override - public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { - PsiFile file = ObjectUtils.tryCast(element, PsiFile.class); - if (file == null || file.getVirtualFile() instanceof VirtualFileWindow) { - return; - } - final Project project = file.getProject(); - final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); - if (!Utils.isEnabled(settings) || PropertiesComponent.getInstance(project).getBoolean(EDITOR_CONFIG_ACCEPTED, false)) return; - final List pairs = SettingsProviderComponent.getInstance().getOutPairs(project, Utils.getFilePath(project, file.getVirtualFile())); - if (!pairs.isEmpty()) { - final Annotation annotation = holder.createInfoAnnotation(file, "EditorConfig is overriding Code Style settings for this file"); - annotation.setFileLevelAnnotation(true); - annotation.setGutterIconRenderer(new MyGutterIconRenderer()); - annotation.registerFix(new IntentionAction() { - @NotNull - @Override - public String getText() { - return "Disable EditorConfig support"; - } - - @NotNull - @Override - public String getFamilyName() { - return "EditorConfig"; - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - settings.getCustomSettings(EditorConfigSettings.class).ENABLED = false; - DaemonCodeAnalyzer.getInstance(project).restart(); - } - - @Override - public boolean startInWriteAction() { - return false; - } - }); - annotation.registerFix(new IntentionAction() { - @NotNull - @Override - public String getText() { - return "Dismiss"; - } - - @NotNull - @Override - public String getFamilyName() { - return "EditorConfig"; - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return true; - } - - @Override - public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { - PropertiesComponent.getInstance(project).setValue(EDITOR_CONFIG_ACCEPTED, "true"); - DaemonCodeAnalyzer.getInstance(project).restart(); - } - - @Override - public boolean startInWriteAction() { - return false; - } - }); - } - } - - private static class MyGutterIconRenderer extends GutterIconRenderer { - @NotNull - @Override - public Icon getIcon() { - return EditorconfigIcons.Editorconfig; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof MyGutterIconRenderer; - } - - @Override - public int hashCode() { - return EditorconfigIcons.Editorconfig.hashCode(); - } - } -} diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/EditorConfigNotifierProvider.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/EditorConfigNotifierProvider.java new file mode 100644 index 000000000000..802cf4b1f1a8 --- /dev/null +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/EditorConfigNotifierProvider.java @@ -0,0 +1,70 @@ +package org.editorconfig.plugincomponents; + +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.TextEditor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.ui.EditorNotificationPanel; +import com.intellij.ui.EditorNotifications; +import com.intellij.ui.LightColors; +import icons.EditorconfigIcons; +import org.editorconfig.Utils; +import org.editorconfig.core.EditorConfig; +import org.editorconfig.settings.EditorConfigSettings; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.List; + +/** + * @author Dennis.Ushakov + */ +public class EditorConfigNotifierProvider extends EditorNotifications.Provider { + private static final Key KEY = Key.create("editor.config.notification.panel"); + private static final String EDITOR_CONFIG_ACCEPTED = "editor.config.accepted"; + + @NotNull + @Override + public Key getKey() { + return KEY; + } + + @Override + public EditorNotificationPanel createNotificationPanel(@NotNull final VirtualFile file, @NotNull final FileEditor fileEditor) { + if (!(fileEditor instanceof TextEditor)) return null; + final Project project = ((TextEditor)fileEditor).getEditor().getProject(); + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings(); + if (!Utils.isEnabled(settings) || PropertiesComponent.getInstance(project).getBoolean(EDITOR_CONFIG_ACCEPTED, false)) return null; + + final List pairs = SettingsProviderComponent.getInstance().getOutPairs(project, Utils.getFilePath(project, file)); + if (!pairs.isEmpty()) { + final EditorNotificationPanel panel = new EditorNotificationPanel() { + @Override + public Color getBackground() { + return LightColors.GREEN; + } + }.text("EditorConfig is overriding Code Style settings for this file"). + icon(EditorconfigIcons.Editorconfig); + panel.createActionLabel("Disable EditorConfig support", new Runnable() { + @Override + public void run() { + settings.getCustomSettings(EditorConfigSettings.class).ENABLED = false; + EditorNotifications.getInstance(project).updateAllNotifications(); + } + }); + panel.createActionLabel("Dismiss", new Runnable() { + @Override + public void run() { + PropertiesComponent.getInstance(project).setValue(EDITOR_CONFIG_ACCEPTED, "true"); + EditorNotifications.getInstance(project).updateAllNotifications(); + } + }); + return panel; + } + return null; + } +} diff --git a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java index f3440dc5eaa7..9458268d05d9 100644 --- a/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java +++ b/plugins/editorconfig/src/org/editorconfig/plugincomponents/SettingsProviderComponent.java @@ -1,12 +1,7 @@ package org.editorconfig.plugincomponents; -import com.intellij.lang.Language; -import com.intellij.lang.LanguageAnnotators; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.ServiceManager; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.openapi.fileTypes.LanguageFileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; @@ -18,7 +13,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import org.editorconfig.Utils; -import org.editorconfig.annotations.EditorConfigAnnotator; import org.editorconfig.core.EditorConfig; import org.editorconfig.core.EditorConfig.OutPair; import org.editorconfig.core.EditorConfigException; @@ -30,25 +24,8 @@ import java.util.*; public class SettingsProviderComponent implements ApplicationComponent { private EditorConfig editorConfig; - public SettingsProviderComponent(FileTypeManager manager) { + public SettingsProviderComponent() { editorConfig = new EditorConfig(); - registerAnnotator(manager); - } - - public void registerAnnotator(FileTypeManager manager) { - final Set languages = new HashSet(); - final EditorConfigAnnotator annotator = new EditorConfigAnnotator(); - for (FileType type : manager.getRegisteredFileTypes()) { - if (type instanceof LanguageFileType) { - final Language lang = ((LanguageFileType)type).getLanguage(); - final String id = lang.getID(); - // don't add annotator for language twice - // don't add annotator for languages not having own annotators - they may rely on parent annotators - if (languages.contains(id) || (lang.getBaseLanguage() != null/* && LanguageAnnotators.INSTANCE.forKey(lang).isEmpty()*/)) continue; - LanguageAnnotators.INSTANCE.addExplicitExtension(lang, annotator); - languages.add(id); - } - } } public static SettingsProviderComponent getInstance() {