From 9e6562fbd06b900bf324d697af159fd349bb555e Mon Sep 17 00:00:00 2001 From: Alexander Zolotov Date: Fri, 22 Feb 2013 18:22:17 +0400 Subject: [PATCH] Emmet support - auto insert vendor prefixes - configurable for emmet --- .../src/messages/XmlBundle.properties | 9 +- .../src/META-INF/XmlPlugin.xml | 6 + .../options/editor/WebEditorOptions.java | 16 +- .../options/editor/WebEditorOptionsForm.form | 37 +-- .../editor/WebEditorOptionsProvider.java | 48 +--- .../emmet/CssEditPrefixesListPanel.java | 190 +++++++++++++++ .../application/options/emmet/CssPrefix.java | 34 +++ .../options/emmet/CssPrefixInfo.java | 116 ++++++++++ .../options/emmet/EmmetConfigurable.form | 89 ++++++++ .../options/emmet/EmmetConfigurable.java | 181 +++++++++++++++ .../emmet/EmmetConfigurableProvider.java | 32 +++ .../options/emmet/EmmetOptions.java | 169 ++++++++++++++ .../options/emmet/emmet_default_options.xml | 216 ++++++++++++++++++ .../template/emmet/ZenCodingTemplate.java | 8 +- .../emmet/filters/BemEmmetFilter.java | 3 +- .../com/intellij/xml/util/ColorIconCache.java | 2 - 16 files changed, 1060 insertions(+), 96 deletions(-) create mode 100644 xml/impl/src/com/intellij/application/options/emmet/CssEditPrefixesListPanel.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/CssPrefix.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/CssPrefixInfo.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.form create mode 100644 xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/EmmetOptions.java create mode 100644 xml/impl/src/com/intellij/application/options/emmet/emmet_default_options.xml diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties index 04ed0e5f9dbe..5bb5b5d3f3ba 100644 --- a/platform/platform-resources-en/src/messages/XmlBundle.properties +++ b/platform/platform-resources-en/src/messages/XmlBundle.properties @@ -241,10 +241,15 @@ label.text.path.to.profiles.ini=Path to \"profiles.ini\": label.text.profile=&Profile: button.text.settings=Settings... display.name.firefox.settings=Firefox Settings -zen.coding.title=XML Zen Coding -zen.coding.enable.label=Enable Zen Coding + +zen.coding.title=Emmet (XML Zen Coding) +emmet.configuration.title=Emmet (Zen Coding) +emmet.auto.insert.vendor.prefixes=Auto insert css vendor prefixes +zen.coding.enable.label=Enable Emmet +emmet.enable.bem.filter=Enable BEM filter by default zen.coding.enter.abbreviation.dialog.label=Please enter an abbreviation zen.coding.incorrect.abbreviation.error=Incorrect abbreviation + title.cannot.create.html.file=Cannot create HTML file new.html.file.action=HTML File new.html.file.action.description=Creates new HTML file diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml index 6cd517927f37..e0eb126d1335 100644 --- a/platform/platform-resources/src/META-INF/XmlPlugin.xml +++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml @@ -149,6 +149,12 @@ serviceImplementation="com.intellij.application.options.editor.WebEditorOptions"/> + + + + + diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java index 570014aba157..fa1f6491e172 100644 --- a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java +++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptions.java @@ -109,18 +109,22 @@ public class WebEditorOptions implements PersistentStateComponent - + @@ -21,7 +21,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -37,43 +37,16 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java index eb1ff2ad95f6..da7f38ae0428 100644 --- a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java +++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java @@ -15,15 +15,11 @@ */ package com.intellij.application.options.editor; -import com.intellij.codeInsight.CodeInsightBundle; -import com.intellij.codeInsight.template.impl.TemplateSettings; import com.intellij.openapi.options.ConfigurationException; import com.intellij.xml.XmlBundle; import org.jetbrains.annotations.NotNull; import javax.swing.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; /** * @author spleaner @@ -34,23 +30,7 @@ public class WebEditorOptionsProvider implements EditorOptionsProvider { private JCheckBox myAutomaticallyInsertRequiredAttributesCheckBox; private JCheckBox myAutomaticallyInsertRequiredSubTagsCheckBox; private JCheckBox myAutomaticallyStartAttributeAfterCheckBox; - private JCheckBox myEnableZenCodingCheckBox; - private JComboBox myZenCodingExpandShortcutCombo; - private static final String SPACE = CodeInsightBundle.message("template.shortcut.space"); - private static final String TAB = CodeInsightBundle.message("template.shortcut.tab"); - private static final String ENTER = CodeInsightBundle.message("template.shortcut.enter"); - - { - myZenCodingExpandShortcutCombo.addItem(SPACE); - myZenCodingExpandShortcutCombo.addItem(TAB); - myZenCodingExpandShortcutCombo.addItem(ENTER); - myEnableZenCodingCheckBox.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - myZenCodingExpandShortcutCombo.setEnabled(myEnableZenCodingCheckBox.isSelected()); - } - }); - } public String getDisplayName() { return XmlBundle.message("web.editor.configuration.title"); @@ -64,24 +44,13 @@ public class WebEditorOptionsProvider implements EditorOptionsProvider { return myWholePanel; } - private char getSelectedZenCodingExpandShortcut() { - Object selectedItem = myZenCodingExpandShortcutCombo.getSelectedItem(); - if (TAB.equals(selectedItem)) { - return TemplateSettings.TAB_CHAR; - } - else if (ENTER.equals(selectedItem)) { - return TemplateSettings.ENTER_CHAR; - } - return TemplateSettings.SPACE_CHAR; - } + public boolean isModified() { final WebEditorOptions xmlEditorOptions = WebEditorOptions.getInstance(); return xmlEditorOptions.isAutomaticallyInsertClosingTag() != myAutomaticallyInsertClosingTagCheckBox.isSelected() || xmlEditorOptions.isAutomaticallyInsertRequiredAttributes() != myAutomaticallyInsertRequiredAttributesCheckBox.isSelected() || xmlEditorOptions.isAutomaticallyStartAttribute() != myAutomaticallyStartAttributeAfterCheckBox.isSelected() || - xmlEditorOptions.isZenCodingEnabled() != myEnableZenCodingCheckBox.isSelected() || - xmlEditorOptions.getZenCodingExpandShortcut() != getSelectedZenCodingExpandShortcut() || xmlEditorOptions.isAutomaticallyInsertRequiredSubTags() != myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected(); } @@ -91,8 +60,6 @@ public class WebEditorOptionsProvider implements EditorOptionsProvider { xmlEditorOptions.setAutomaticallyInsertRequiredAttributes(myAutomaticallyInsertRequiredAttributesCheckBox.isSelected()); xmlEditorOptions.setAutomaticallyInsertRequiredSubTags(myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected()); xmlEditorOptions.setAutomaticallyStartAttribute(myAutomaticallyStartAttributeAfterCheckBox.isSelected()); - xmlEditorOptions.setZenCodingEnabled(myEnableZenCodingCheckBox.isSelected()); - xmlEditorOptions.setZenCodingExpandShortcut(getSelectedZenCodingExpandShortcut()); } public void reset() { @@ -101,19 +68,6 @@ public class WebEditorOptionsProvider implements EditorOptionsProvider { myAutomaticallyInsertRequiredAttributesCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredAttributes()); myAutomaticallyInsertRequiredSubTagsCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredSubTags()); myAutomaticallyStartAttributeAfterCheckBox.setSelected(xmlEditorOptions.isAutomaticallyStartAttribute()); - myEnableZenCodingCheckBox.setSelected(xmlEditorOptions.isZenCodingEnabled()); - myZenCodingExpandShortcutCombo.setEnabled(xmlEditorOptions.isZenCodingEnabled()); - - char shortcut = (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut(); - if (shortcut == TemplateSettings.TAB_CHAR) { - myZenCodingExpandShortcutCombo.setSelectedItem(TAB); - } - else if (shortcut == TemplateSettings.ENTER_CHAR) { - myZenCodingExpandShortcutCombo.setSelectedItem(ENTER); - } - else { - myZenCodingExpandShortcutCombo.setSelectedItem(SPACE); - } } public void disposeUIResources() { diff --git a/xml/impl/src/com/intellij/application/options/emmet/CssEditPrefixesListPanel.java b/xml/impl/src/com/intellij/application/options/emmet/CssEditPrefixesListPanel.java new file mode 100644 index 000000000000..aa6d6ec5620d --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/CssEditPrefixesListPanel.java @@ -0,0 +1,190 @@ +/* + * Copyright 2000-2013 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.emmet; + +import com.intellij.openapi.ui.Messages; +import com.intellij.ui.*; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.ui.table.TableView; +import com.intellij.util.ui.ColumnInfo; +import com.intellij.util.ui.ListTableModel; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.table.TableCellEditor; +import javax.swing.table.TableCellRenderer; +import java.util.ArrayList; +import java.util.List; + +/** + * User: zolotov + * Date: 2/20/13 + */ +public class CssEditPrefixesListPanel { + private final ListTableModel myPrefixesModel; + private final TableView myPrefixesTableView; + + public CssEditPrefixesListPanel() { + ColumnInfo[] columns = new ColumnInfo[CssPrefix.values().length + 1]; + columns[0] = new PropertyColumn(); + CssPrefix[] values = CssPrefix.values(); + for (int i = 0; i < values.length; i++) { + columns[i + 1] = new PrefixColumnInfo(values[i]); + } + + myPrefixesModel = new ListTableModel(columns, new ArrayList(), 0); + myPrefixesModel.setSortable(true); + myPrefixesTableView = new TableView(myPrefixesModel); + myPrefixesTableView.setAutoCreateRowSorter(true); + myPrefixesTableView.setBorder(null); + myPrefixesTableView.getRowSorter().toggleSortOrder(0); + + new TableViewSpeedSearch(myPrefixesTableView) { + @Override + protected String getElementText(final Object element) { + CssPrefixInfo prefixInfo = (CssPrefixInfo)element; + return prefixInfo.getPropertyName(); + } + }; + } + + public void setEnabled(boolean value) { + myPrefixesTableView.setEnabled(value); + } + + public void setState(List prefixInfos) { + myPrefixesModel.setItems(prefixInfos); + } + + public List getState() { + return myPrefixesModel.getItems(); + } + + public JPanel createMainComponent() { + final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myPrefixesTableView); + decorator.disableUpDownActions(); + final JPanel panel = decorator.createPanel(); + decorator.setAddAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + TableUtil.stopEditing(myPrefixesTableView); + String propertyName = Messages.showInputDialog(myPrefixesTableView, "Property name:", "New Css Property", null); + if (propertyName != null && !propertyName.isEmpty()) { + List items = myPrefixesModel.getItems(); + for (CssPrefixInfo state : items) { + if (propertyName.equals(state.getPropertyName())) { + myPrefixesTableView.clearSelection(); + myPrefixesTableView.addSelection(state); + scrollToSelection(); + return; + } + } + CssPrefixInfo newPrefixInfo = new CssPrefixInfo(propertyName); + myPrefixesModel.addRow(newPrefixInfo); + myPrefixesTableView.clearSelection(); + myPrefixesTableView.addSelection(newPrefixInfo); + scrollToSelection(); + } + myPrefixesTableView.requestFocus(); + } + + private void scrollToSelection() { + int selectedRow = myPrefixesTableView.getSelectedRow(); + if (selectedRow >= 0) { + myPrefixesTableView.scrollRectToVisible(myPrefixesTableView.getCellRect(selectedRow, 0, true)); + } + } + }).setRemoveAction(new AnActionButtonRunnable() { + @Override + public void run(AnActionButton button) { + TableUtil.stopEditing(myPrefixesTableView); + CssPrefixInfo selectedObject = myPrefixesTableView.getSelectedObject(); + int selectedRow = myPrefixesTableView.getSelectedRow(); + int index = myPrefixesModel.indexOf(selectedObject); + if (0 <= index && index < myPrefixesModel.getRowCount()) { + myPrefixesModel.removeRow(index); + if (selectedRow < myPrefixesTableView.getRowCount()) { + myPrefixesTableView.setRowSelectionInterval(selectedRow, selectedRow); + } + else { + if (selectedRow > 0) { + myPrefixesTableView.setRowSelectionInterval(selectedRow - 1, selectedRow - 1); + } + } + } + myPrefixesTableView.getParent().repaint(); + myPrefixesTableView.requestFocus(); + } + }); + return panel; + } + + private static class PropertyColumn extends ColumnInfo { + public PropertyColumn() { + super("Property"); + } + + @Nullable + @Override + public String valueOf(CssPrefixInfo prefixInfo) { + return prefixInfo.getPropertyName(); + } + } + + private class PrefixColumnInfo extends ColumnInfo { + private final CssPrefix myPrefix; + private final BooleanTableCellRenderer myCellRenderer = new BooleanTableCellRenderer(); + + @Nullable + @Override + public TableCellRenderer getRenderer(CssPrefixInfo state) { + return myCellRenderer; + } + + public PrefixColumnInfo(CssPrefix prefix) { + super(prefix.getText()); + myPrefix = prefix; + } + + @Nullable + @Override + public TableCellEditor getEditor(CssPrefixInfo prefixInfo) { + JBCheckBox box = new JBCheckBox(); + box.setHorizontalAlignment(SwingConstants.CENTER); + return new DefaultCellEditor(box); + } + + @Override + public boolean isCellEditable(CssPrefixInfo prefixInfo) { + return myPrefixesTableView.isEnabled(); + } + + public final Class getColumnClass() { + return Boolean.class; + } + + @Override + public final void setValue(final CssPrefixInfo prefixInfo, final Boolean aValue) { + prefixInfo.setValue(myPrefix, aValue); + } + + @Nullable + @Override + public final Boolean valueOf(CssPrefixInfo state) { + return state.getValue(myPrefix); + } + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/CssPrefix.java b/xml/impl/src/com/intellij/application/options/emmet/CssPrefix.java new file mode 100644 index 000000000000..da3bae3ab476 --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/CssPrefix.java @@ -0,0 +1,34 @@ +/* + * Copyright 2000-2013 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.emmet; + +/** +* User: zolotov +* Date: 2/21/13 +*/ +public enum CssPrefix { + WEBKIT(0x1), MOZ(0x2), MS(0x4), O(0x8); + + final int myIntMask; + + CssPrefix(int intMask) { + myIntMask = intMask; + } + + public String getText() { + return "-" + toString().toLowerCase(); + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/CssPrefixInfo.java b/xml/impl/src/com/intellij/application/options/emmet/CssPrefixInfo.java new file mode 100644 index 000000000000..f31443ce9e4b --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/CssPrefixInfo.java @@ -0,0 +1,116 @@ +/* + * Copyright 2000-2013 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.emmet; + +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Sets.newHashSet; + +/** + * User: zolotov + * Date: 2/20/13 + */ +public class CssPrefixInfo { + @NotNull + private final String myPropertyName; + @NotNull + private final Collection myEnabledPrefixes; + + public CssPrefixInfo(@NotNull String propertyName, CssPrefix... enabledPrefixes) { + myPropertyName = propertyName; + myEnabledPrefixes = newHashSet(enabledPrefixes); + for (CssPrefix prefix : enabledPrefixes) { + setValue(prefix, true); + } + } + + public CssPrefixInfo(@NotNull String propertyName, Collection enabledPrefixes) { + myPropertyName = propertyName; + myEnabledPrefixes = newHashSet(enabledPrefixes); + for (CssPrefix prefix : enabledPrefixes) { + setValue(prefix, true); + } + } + + @NotNull + public Collection getEnabledPrefixes() { + return myEnabledPrefixes; + } + + public void setValue(CssPrefix prefix, boolean value) { + if (value) { + myEnabledPrefixes.add(prefix); + } else { + myEnabledPrefixes.remove(prefix); + } + } + + public boolean getValue(CssPrefix prefix) { + return myEnabledPrefixes.contains(prefix); + } + + @NotNull + public String getPropertyName() { + return myPropertyName; + } + + public static CssPrefixInfo fromIntegerValue(String propertyName, Integer value) { + if (value == null) { + return new CssPrefixInfo(propertyName); + } + List enabledPrefixes = newArrayList(); + for (CssPrefix prefix : CssPrefix.values()) { + if ((value & prefix.myIntMask) > 0) { + enabledPrefixes.add(prefix); + } + } + return new CssPrefixInfo(propertyName, enabledPrefixes); + } + + public int toIntegerValue() { + int result = 0; + for (CssPrefix prefix : myEnabledPrefixes) { + if (getValue(prefix)) { + result |= prefix.myIntMask; + } + } + return result; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + CssPrefixInfo that = (CssPrefixInfo)o; + + if (!myEnabledPrefixes.equals(that.myEnabledPrefixes)) return false; + if (!myPropertyName.equals(that.myPropertyName)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myPropertyName.hashCode(); + result = 31 * result + myEnabledPrefixes.hashCode(); + return result; + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.form b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.form new file mode 100644 index 000000000000..62127bcf42e3 --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.form @@ -0,0 +1,89 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.java b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.java new file mode 100644 index 000000000000..5f69489785da --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurable.java @@ -0,0 +1,181 @@ +/* + * Copyright 2000-2013 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.emmet; + +import com.intellij.codeInsight.CodeInsightBundle; +import com.intellij.codeInsight.template.impl.TemplateSettings; +import com.intellij.openapi.Disposable; +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurationException; +import com.intellij.openapi.options.SearchableConfigurable; +import com.intellij.ui.components.JBCheckBox; +import com.intellij.xml.XmlBundle; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + * User: zolotov + * Date: 2/20/13 + */ +public class EmmetConfigurable implements SearchableConfigurable, Disposable, Configurable.NoScroll { + private JBCheckBox myEnableEmmetJBCheckBox; + private JComboBox myEmmetExpandShortcutCombo; + private JBCheckBox myEnableBEMFilterJBCheckBox; + private JBCheckBox myAutoInsertCssVendorJBCheckBox; + private JPanel myPanel; + private JPanel myPrefixesPanel; + + private CssEditPrefixesListPanel myCssEditPrefixesListPanel; + + private static final String SPACE = CodeInsightBundle.message("template.shortcut.space"); + private static final String TAB = CodeInsightBundle.message("template.shortcut.tab"); + private static final String ENTER = CodeInsightBundle.message("template.shortcut.enter"); + + public EmmetConfigurable() { + myEnableEmmetJBCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + boolean selected = myEnableEmmetJBCheckBox.isSelected(); + myEmmetExpandShortcutCombo.setEnabled(selected); + //myInsertFallbackGradientColorJBCheckBox.setEnabled(selected); + myAutoInsertCssVendorJBCheckBox.setEnabled(selected); + myCssEditPrefixesListPanel.setEnabled(selected && myAutoInsertCssVendorJBCheckBox.isSelected()); + myEnableBEMFilterJBCheckBox.setEnabled(selected); + } + }); + + myAutoInsertCssVendorJBCheckBox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + myCssEditPrefixesListPanel.setEnabled(myAutoInsertCssVendorJBCheckBox.isSelected()); + } + }); + + myEmmetExpandShortcutCombo.addItem(SPACE); + myEmmetExpandShortcutCombo.addItem(TAB); + myEmmetExpandShortcutCombo.addItem(ENTER); + } + + private char getSelectedEmmetExpandShortcut() { + Object selectedItem = myEmmetExpandShortcutCombo.getSelectedItem(); + if (TAB.equals(selectedItem)) { + return TemplateSettings.TAB_CHAR; + } + else if (ENTER.equals(selectedItem)) { + return TemplateSettings.ENTER_CHAR; + } + return TemplateSettings.SPACE_CHAR; + } + + @Override + public void dispose() { + } + + @NotNull + @Override + public String getId() { + return "reference.settingsdialog.emmet"; + } + + @Nullable + @Override + public Runnable enableSearch(String option) { + return null; + } + + @Nls + @Override + public String getDisplayName() { + return XmlBundle.message("emmet.configuration.title"); + } + + @Nullable + @Override + public String getHelpTopic() { + return getId(); + } + + @Nullable + @Override + public JComponent createComponent() { + return myPanel; + } + + @Override + public boolean isModified() { + EmmetOptions emmetOptions = EmmetOptions.getInstance(); + return emmetOptions.isEmmetEnabled() != myEnableEmmetJBCheckBox.isSelected() || + emmetOptions.isBemFilterEnabledByDefault() != myEnableBEMFilterJBCheckBox.isSelected() || + emmetOptions.isAutoInsertCssPrefixedEnabled() != myAutoInsertCssVendorJBCheckBox.isSelected() || + !emmetOptions.getAllPrefixInfo().equals(myCssEditPrefixesListPanel.getState()) || + emmetOptions.getEmmetExpandShortcut() != getSelectedEmmetExpandShortcut(); + } + + + @Override + public void apply() throws ConfigurationException { + EmmetOptions emmetOptions = EmmetOptions.getInstance(); + emmetOptions.setEmmetEnabled(myEnableEmmetJBCheckBox.isSelected()); + emmetOptions.setEnableBemFilterByDefault(myEnableBEMFilterJBCheckBox.isSelected()); + emmetOptions.setEmmetExpandShortcut(getSelectedEmmetExpandShortcut()); + emmetOptions.setAutoInsertCssPrefixedEnabled(myAutoInsertCssVendorJBCheckBox.isSelected()); + emmetOptions.setPrefixInfo(myCssEditPrefixesListPanel.getState()); + } + + @Override + public void reset() { + EmmetOptions emmetOptions = EmmetOptions.getInstance(); + myEnableEmmetJBCheckBox.setSelected(emmetOptions.isEmmetEnabled()); + myEnableBEMFilterJBCheckBox.setEnabled(emmetOptions.isEmmetEnabled()); + myEnableBEMFilterJBCheckBox.setSelected(emmetOptions.isBemFilterEnabledByDefault()); + myEmmetExpandShortcutCombo.setEnabled(emmetOptions.isEmmetEnabled()); + myAutoInsertCssVendorJBCheckBox.setEnabled(emmetOptions.isEmmetEnabled()); + myAutoInsertCssVendorJBCheckBox.setSelected(emmetOptions.isAutoInsertCssPrefixedEnabled()); + //myInsertFallbackGradientColorJBCheckBox.setEnabled(emmetOptions.isEmmetEnabled()); + //myInsertFallbackGradientColorJBCheckBox.setSelected(emmetOptions.isInsertFallbackGradientColorEnabled()); + + myCssEditPrefixesListPanel.setEnabled(emmetOptions.isEmmetEnabled() && emmetOptions.isAutoInsertCssPrefixedEnabled()); + myCssEditPrefixesListPanel.setState(emmetOptions.getAllPrefixInfo()); + + char shortcut = (char)emmetOptions.getEmmetExpandShortcut(); + if (shortcut == TemplateSettings.TAB_CHAR) { + myEmmetExpandShortcutCombo.setSelectedItem(TAB); + } + else if (shortcut == TemplateSettings.ENTER_CHAR) { + myEmmetExpandShortcutCombo.setSelectedItem(ENTER); + } + else { + myEmmetExpandShortcutCombo.setSelectedItem(SPACE); + } + } + + @Override + public void disposeUIResources() { + myCssEditPrefixesListPanel = null; + myPrefixesPanel = null; + } + + private void createUIComponents() { + myCssEditPrefixesListPanel = new CssEditPrefixesListPanel(); + myPrefixesPanel = myCssEditPrefixesListPanel.createMainComponent(); + myPrefixesPanel.setEnabled(true); + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java new file mode 100644 index 000000000000..2d13a7382516 --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetConfigurableProvider.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2013 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.emmet; + +import com.intellij.openapi.options.Configurable; +import com.intellij.openapi.options.ConfigurableProvider; +import org.jetbrains.annotations.Nullable; + +/** + * User: zolotov + * Date: 2/20/13 + */ +public class EmmetConfigurableProvider extends ConfigurableProvider { + @Nullable + @Override + public Configurable createConfigurable() { + return new EmmetConfigurable(); + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/EmmetOptions.java b/xml/impl/src/com/intellij/application/options/emmet/EmmetOptions.java new file mode 100644 index 000000000000..70ddaa453aae --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/EmmetOptions.java @@ -0,0 +1,169 @@ +/* + * Copyright 2000-2013 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.emmet; + +import com.intellij.application.options.editor.WebEditorOptions; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.components.*; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.xmlb.XmlSerializerUtil; +import com.intellij.xml.XmlBundle; +import org.jdom.Document; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Lists.newLinkedList; +import static com.google.common.collect.Maps.newHashMap; +import static com.google.common.io.Resources.getResource; + +/** + * User: zolotov + * Date: 2/20/13 + */ +@State( + name = "EmmetOptions", + storages = { + @Storage( + file = StoragePathMacros.APP_CONFIG + "/emmet.xml" + )} +) +public class EmmetOptions implements PersistentStateComponent, ExportableComponent { + private boolean myEnableBemFilterByDefault = false; + private boolean myEmmetEnabled = WebEditorOptions.getInstance().isZenCodingEnabled(); + private int myEmmetExpandShortcut = WebEditorOptions.getInstance().getZenCodingExpandShortcut(); + private boolean myAutoInsertCssPrefixedEnabled = true; + @Nullable + private Map prefixes = null; + + public void setPrefixInfo(List prefixInfos) { + prefixes = newHashMap(); + for (CssPrefixInfo state : prefixInfos) { + prefixes.put(state.getPropertyName(), state.toIntegerValue()); + } + } + + public CssPrefixInfo getPrefixStateForProperty(String propertyName) { + return CssPrefixInfo.fromIntegerValue(propertyName, getPrefixes().get(propertyName)); + } + + public List getAllPrefixInfo() { + List result = newLinkedList(); + for (Map.Entry entry : getPrefixes().entrySet()) { + result.add(CssPrefixInfo.fromIntegerValue(entry.getKey(), entry.getValue())); + } + return result; + } + + public boolean isBemFilterEnabledByDefault() { + return myEnableBemFilterByDefault; + } + + public void setEnableBemFilterByDefault(boolean enableBemFilterByDefault) { + myEnableBemFilterByDefault = enableBemFilterByDefault; + } + + public void setEmmetExpandShortcut(int emmetExpandShortcut) { + myEmmetExpandShortcut = emmetExpandShortcut; + } + + public int getEmmetExpandShortcut() { + return myEmmetExpandShortcut; + } + + public boolean isEmmetEnabled() { + return myEmmetEnabled; + } + + public void setEmmetEnabled(boolean emmetEnabled) { + myEmmetEnabled = emmetEnabled; + } + + public boolean isAutoInsertCssPrefixedEnabled() { + return myAutoInsertCssPrefixedEnabled; + } + + public void setAutoInsertCssPrefixedEnabled(boolean autoInsertCssPrefixedEnabled) { + myAutoInsertCssPrefixedEnabled = autoInsertCssPrefixedEnabled; + } + + @NotNull + @Override + public File[] getExportFiles() { + return new File[]{PathManager.getOptionsFile("emmet")}; + } + + @NotNull + @Override + public String getPresentableName() { + return XmlBundle.message("emmet.configuration.title"); + } + + @Nullable + @Override + public EmmetOptions getState() { + return this; + } + + public void loadState(final EmmetOptions state) { + XmlSerializerUtil.copyBean(state, this); + } + + public static EmmetOptions getInstance() { + return ServiceManager.getService(EmmetOptions.class); + } + + @SuppressWarnings("UnusedDeclaration") + @NotNull + public Map getPrefixes() { + if (prefixes == null) { + prefixes = loadDefaultPrefixes(); + } + return prefixes; + } + + @SuppressWarnings("UnusedDeclaration") + public void setPrefixes(@Nullable Map prefixes) { + this.prefixes = prefixes; + } + + public static Map loadDefaultPrefixes() { + Map result = newHashMap(); + try { + Document document = JDOMUtil.loadDocument(getResource(EmmetOptions.class, "emmet_default_options.xml")); + Element prefixesElement = document.getRootElement().getChild("prefixes"); + if (prefixesElement != null) { + for (Object entry : prefixesElement.getChildren("entry")) { + Element entryElement = (Element)entry; + String propertyName = entryElement.getAttributeValue("key"); + Integer value = StringUtil.parseInt(entryElement.getAttributeValue("value"), 0); + result.put(propertyName, value); + } + } + } + catch (Exception e) { + Logger.getInstance(EmmetOptions.class).warn(e); + return result; + } + return result; + } +} diff --git a/xml/impl/src/com/intellij/application/options/emmet/emmet_default_options.xml b/xml/impl/src/com/intellij/application/options/emmet/emmet_default_options.xml new file mode 100644 index 000000000000..287ab5f703f3 --- /dev/null +++ b/xml/impl/src/com/intellij/application/options/emmet/emmet_default_options.xml @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java index 6f4e29d58187..5d3ab8730412 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java @@ -15,7 +15,7 @@ */ package com.intellij.codeInsight.template.emmet; -import com.intellij.application.options.editor.WebEditorOptions; +import com.intellij.application.options.emmet.EmmetOptions; import com.intellij.codeInsight.CodeInsightBundle; import com.intellij.codeInsight.template.*; import com.intellij.codeInsight.template.emmet.filters.SingleLineEmmetFilter; @@ -276,8 +276,8 @@ public class ZenCodingTemplate implements CustomLiveTemplate { } public boolean isApplicable(PsiFile file, int offset, boolean wrapping) { - WebEditorOptions webEditorOptions = WebEditorOptions.getInstance(); - if (!webEditorOptions.isZenCodingEnabled()) { + EmmetOptions emmetOptions = EmmetOptions.getInstance(); + if (!emmetOptions.isEmmetEnabled()) { return false; } if (file == null) { @@ -320,7 +320,7 @@ public class ZenCodingTemplate implements CustomLiveTemplate { } public char getShortcut() { - return (char)WebEditorOptions.getInstance().getZenCodingExpandShortcut(); + return (char)EmmetOptions.getInstance().getEmmetExpandShortcut(); } public String computeTemplateKey(@NotNull CustomTemplateCallback callback) { diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/BemEmmetFilter.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/BemEmmetFilter.java index f226864dd2c1..69b1adf67d8f 100644 --- a/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/BemEmmetFilter.java +++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/filters/BemEmmetFilter.java @@ -20,6 +20,7 @@ import com.google.common.base.Joiner; import com.google.common.base.Predicate; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableSet; +import com.intellij.application.options.emmet.EmmetOptions; import com.intellij.codeInsight.template.emmet.nodes.GenerationNode; import com.intellij.lang.xml.XMLLanguage; import com.intellij.openapi.util.Key; @@ -94,7 +95,7 @@ public class BemEmmetFilter extends ZenCodingFilter { @Override public boolean isAppliedByDefault(@NotNull PsiElement context) { - return false; //todo: add setting for enabling this filter by default + return EmmetOptions.getInstance().isBemFilterEnabledByDefault(); } @Override diff --git a/xml/impl/src/com/intellij/xml/util/ColorIconCache.java b/xml/impl/src/com/intellij/xml/util/ColorIconCache.java index 15b31716e5ca..c0f01ad354eb 100644 --- a/xml/impl/src/com/intellij/xml/util/ColorIconCache.java +++ b/xml/impl/src/com/intellij/xml/util/ColorIconCache.java @@ -17,7 +17,6 @@ package com.intellij.xml.util; import com.intellij.util.containers.HashMap; import com.intellij.util.containers.SoftFactoryMap; -import com.intellij.util.containers.WeakFactoryMap; import com.intellij.util.ui.EmptyIcon; import org.jetbrains.annotations.NotNull; @@ -44,7 +43,6 @@ public class ColorIconCache { return INSTANCE; } - @SuppressWarnings({"MethodMayBeStatic"}) public Icon getIcon(@NotNull final Color color, final int size) { Icon icon = ourCache.get(color).get(size); if (icon == null) {