Modified color and code style schemes highlighting in schemes combo

This commit is contained in:
Rustam Vishnyakov
2017-01-26 18:39:53 +03:00
parent 869e2b9b80
commit 6e1b659f29
19 changed files with 267 additions and 39 deletions
@@ -889,9 +889,12 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
return root;
}
public boolean isEqualToBundled(AbstractColorsScheme bundledScheme) {
public boolean equals(Object other) {
if (!(other instanceof AbstractColorsScheme)) return false;
AbstractColorsScheme otherScheme = (AbstractColorsScheme)other;
// parent is used only for default schemes (e.g. Darcula — bundled in all ide (opposite to IDE-specific, like Cobalt))
if (myParentScheme != bundledScheme.myParentScheme && myParentScheme != bundledScheme) {
if (getBaseDefaultScheme(this) != getBaseDefaultScheme(otherScheme)) {
return false;
}
@@ -903,23 +906,39 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
propertyName.equals(META_INFO_ORIGINAL)
) {
continue;
}
}
if (!Comparing.equal(myMetaInfo.getProperty(propertyName), bundledScheme.myMetaInfo.getProperty(propertyName))) {
if (!Comparing.equal(myMetaInfo.getProperty(propertyName), otherScheme.myMetaInfo.getProperty(propertyName))) {
return false;
}
}
return getLineSpacing() == bundledScheme.getLineSpacing() &&
getConsoleLineSpacing() == bundledScheme.getConsoleLineSpacing() &&
getQuickDocFontSize() == bundledScheme.getQuickDocFontSize() &&
myFontPreferences.getRealFontFamilies().equals(bundledScheme.myFontPreferences.getRealFontFamilies()) &&
myFontPreferences.useLigatures() == bundledScheme.myFontPreferences.useLigatures() &&
myConsoleFontPreferences.useLigatures() == bundledScheme.myConsoleFontPreferences.useLigatures() &&
myConsoleFontPreferences.getRealFontFamilies().equals(bundledScheme.myConsoleFontPreferences.getRealFontFamilies()) &&
myColorsMap.equals(bundledScheme.myColorsMap) &&
myAttributesMap.equals(bundledScheme.myAttributesMap) &&
myFontPreferences.equals(bundledScheme.myFontPreferences) &&
myConsoleFontPreferences.equals(bundledScheme.myConsoleFontPreferences);
return getLineSpacing() == otherScheme.getLineSpacing() &&
getConsoleLineSpacing() == otherScheme.getConsoleLineSpacing() &&
myFontPreferences.equals(otherScheme.getFontPreferences()) &&
myConsoleFontPreferences.equals(otherScheme.getConsoleFontPreferences()) &&
attributesEqual(otherScheme) &&
colorsEqual(otherScheme) &&
myFontPreferences.equals(otherScheme.myFontPreferences);
}
protected boolean attributesEqual(AbstractColorsScheme otherScheme) {
return myAttributesMap.equals(otherScheme.myAttributesMap);
}
protected boolean colorsEqual(AbstractColorsScheme otherScheme) {
return myColorsMap.equals(otherScheme.myColorsMap);
}
@Nullable
private static EditorColorsScheme getBaseDefaultScheme(@NotNull EditorColorsScheme scheme) {
if (!(scheme instanceof AbstractColorsScheme)) {
return null;
}
if (scheme instanceof DefaultColorsScheme) {
return scheme;
}
EditorColorsScheme parent = ((AbstractColorsScheme)scheme).myParentScheme;
return parent != null ? getBaseDefaultScheme(parent) : null;
}
}
@@ -25,6 +25,9 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Function;
import static com.intellij.openapi.editor.markup.TextAttributes.USE_INHERITED_MARKER;
@@ -85,4 +88,64 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte
newScheme.setDefaultMetaInfo(this);
return newScheme;
}
@Override
protected boolean attributesEqual(AbstractColorsScheme otherScheme) {
return compareAttributes(otherScheme, new ArrayList<>());
}
@Override
protected boolean colorsEqual(AbstractColorsScheme otherScheme) {
return compareColors(otherScheme, new ArrayList<>());
}
private boolean compareAttributes(@NotNull AbstractColorsScheme otherScheme,
@NotNull Collection<Function<TextAttributesKey, Boolean>> filters) {
for (TextAttributesKey key : myAttributesMap.keySet()) {
if (!isTextAttributeKeyIgnored(filters, key) && !getAttributes(key).equals(otherScheme.getAttributes(key))) {
return false;
}
}
filters.add(key -> myAttributesMap.containsKey(key));
if (myParentScheme instanceof EditorColorsSchemeImpl &&
!((EditorColorsSchemeImpl)myParentScheme).compareAttributes(otherScheme, filters)) {
return false;
}
return true;
}
private static boolean isTextAttributeKeyIgnored(@NotNull Collection<Function<TextAttributesKey, Boolean>> filters,
TextAttributesKey key) {
for (Function<TextAttributesKey, Boolean> filter : filters) {
if (filter.apply(key)) return true;
}
return false;
}
private boolean compareColors(@NotNull AbstractColorsScheme otherScheme,
@NotNull Collection<Function<ColorKey, Boolean>> filters) {
for (ColorKey key : myColorsMap.keySet()) {
Color thisColor = getColor(key);
Color otherColor = otherScheme.getColor(key);
if (thisColor == null) {
return otherColor == null;
}
if (!isColorKeyIgnored(filters, key) && !thisColor.equals(otherColor)) {
return false;
}
}
filters.add(key -> myColorsMap.containsKey(key));
if (myParentScheme instanceof EditorColorsSchemeImpl &&
!((EditorColorsSchemeImpl)myParentScheme).compareColors(otherScheme, filters)) {
return false;
}
return true;
}
private static boolean isColorKeyIgnored(@NotNull Collection<Function<ColorKey, Boolean>> filters, ColorKey key) {
for (Function<ColorKey,Boolean> filter : filters) {
if (filter.apply(key)) return false;
}
return true;
}
}
@@ -35,6 +35,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.Processor;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ClassMap;
import org.jdom.Element;
@@ -61,6 +62,8 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
@NonNls private static final String FILETYPE = "fileType";
private CommonCodeStyleSettingsManager myCommonSettingsManager = new CommonCodeStyleSettingsManager(this);
private static CodeStyleSettings myDefaults;
private UnknownElementWriter myUnknownElementWriter = UnknownElementWriter.EMPTY;
public CodeStyleSettings() {
@@ -1049,4 +1052,22 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
this.quote = quote;
}
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CodeStyleSettings)) return false;
if (!ReflectionUtil.comparePublicNonFinalFields(this, obj)) return false;
if (!myCommonSettingsManager.equals(((CodeStyleSettings)obj).myCommonSettingsManager)) return false;
for (CustomCodeStyleSettings customSettings : myCustomSettings.values()) {
if (!customSettings.equals(((CodeStyleSettings)obj).getCustomSettings(customSettings.getClass()))) return false;
}
return true;
}
public static CodeStyleSettings getDefaults() {
if (myDefaults == null) {
myDefaults = new CodeStyleSettings();
}
return myDefaults;
}
}
@@ -1041,4 +1041,17 @@ public class CommonCodeStyleSettings {
myOverrideLanguageOptions = overrideLanguageOptions;
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CommonCodeStyleSettings) {
if (
ReflectionUtil.comparePublicNonFinalFields(this, obj) &&
myIndentOptions.equals(((CommonCodeStyleSettings)obj).getIndentOptions())
) {
return true;
}
}
return false;
}
}
@@ -231,4 +231,21 @@ public class CommonCodeStyleSettingsManager {
}
}
}
@Override
public boolean equals(Object obj) {
if (obj instanceof CommonCodeStyleSettingsManager) {
CommonCodeStyleSettingsManager other = (CommonCodeStyleSettingsManager)obj;
if (getCommonSettingsMap().size() != other.getCommonSettingsMap().size() ||
myUnknownSettingsMap.size() != other.myUnknownSettingsMap.size()) {
return false;
}
for (Language language : myCommonSettingsMap.keySet()) {
CommonCodeStyleSettings theseSettings = myCommonSettingsMap.get(language);
CommonCodeStyleSettings otherSettings = other.getCommonSettings(language);
if (!theseSettings.equals(otherSettings)) return false;
}
}
return true;
}
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.DifferenceFilter;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.ReflectionUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -86,4 +87,11 @@ public abstract class CustomCodeStyleSettings implements Cloneable {
*/
protected void importLegacySettings() {
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof CustomCodeStyleSettings)) return false;
if (!ReflectionUtil.comparePublicNonFinalFields(this, obj)) return false;
return true;
}
}
@@ -133,7 +133,7 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
protected void somethingChanged() {
if (myModel != null) {
myModel.fireCurrentSettingsChanged();
myModel.fireBeforeCurrentSettingsChanged();
}
}
@@ -212,6 +212,9 @@ public abstract class CodeStyleAbstractPanel implements Disposable {
try {
apply(mySettings);
if (myModel != null) {
myModel.fireAfterCurrentSettingsChanged();
}
}
catch (ConfigurationException ignore) {
}
@@ -231,8 +231,11 @@ public class CodeStyleSchemesConfigurable extends SearchableConfigurable.Parent.
}
@Override
public void currentSettingsChanged() {
public void beforeCurrentSettingsChanged() {
}
@Override
public void afterCurrentSettingsChanged() {
}
@Override
@@ -95,12 +95,17 @@ public class CodeStyleMainPanel extends JPanel implements TabbedLanguageCodeStyl
}
@Override
public void currentSettingsChanged() {
public void beforeCurrentSettingsChanged() {
if (!myIsDisposed) {
ensureCurrentPanel().onSomethingChanged();
}
}
@Override
public void afterCurrentSettingsChanged() {
mySchemesPanel.updateOnCurrentSettingsChange();
}
@Override
public void usePerProjectSettingsOptionChanged() {
mySchemesPanel.usePerProjectSettingsOptionChanged();
@@ -179,8 +179,8 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
return false;
}
public void fireCurrentSettingsChanged() {
myDispatcher.getMulticaster().currentSettingsChanged();
public void fireBeforeCurrentSettingsChanged() {
myDispatcher.getMulticaster().beforeCurrentSettingsChanged();
}
public void fireSchemeChanged(CodeStyleScheme scheme) {
@@ -190,6 +190,10 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
public void fireSchemeListChanged() {
myDispatcher.getMulticaster().schemeListChanged();
}
public void fireAfterCurrentSettingsChanged() {
myDispatcher.getMulticaster().afterCurrentSettingsChanged();
}
public CodeStyleScheme getSelectedGlobalScheme() {
return myGlobalSelected;
@@ -238,7 +242,7 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
@Override
public boolean canResetScheme(@NotNull CodeStyleScheme scheme) {
return true;
return scheme.isDefault();
}
@Override
@@ -261,6 +265,13 @@ public class CodeStyleSchemesModel implements SchemesModel<CodeStyleScheme> {
return findSchemeByName(name) != null;
}
@Override
public boolean differsFromDefault(@NotNull CodeStyleScheme scheme) {
CodeStyleSettings defaults = CodeStyleSettings.getDefaults();
CodeStyleSettings clonedSettings = getCloneSettings(scheme);
return !defaults.equals(clonedSettings);
}
public List<CodeStyleScheme> getAllSortedSchemes() {
List<CodeStyleScheme> schemes = new ArrayList<>();
schemes.addAll(getSchemes());
@@ -25,7 +25,9 @@ public interface CodeStyleSettingsListener extends EventListener {
void schemeListChanged();
void currentSettingsChanged();
void beforeCurrentSettingsChanged();
void afterCurrentSettingsChanged();
void usePerProjectSettingsOptionChanged();
@@ -29,6 +29,7 @@ import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.editor.colors.*;
import com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager;
import com.intellij.openapi.editor.colors.impl.*;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
@@ -192,6 +193,21 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract
return mySchemes.get(name) != null || mySchemes.get(SchemeManager.EDITABLE_COPY_PREFIX + name) != null;
}
@Override
public boolean differsFromDefault(@NotNull EditorColorsScheme scheme) {
if (scheme.getName().startsWith(SchemeManager.EDITABLE_COPY_PREFIX)) {
String displayName = SchemeManager.getDisplayName(scheme);
EditorColorsScheme defaultScheme = DefaultColorSchemesManager.getInstance().getScheme(displayName);
if (defaultScheme == null) {
defaultScheme = EditorColorsManager.getInstance().getScheme(displayName);
}
if (defaultScheme != null) {
return !scheme.equals(defaultScheme);
}
}
return false;
}
public static boolean isReadOnly(@NotNull final EditorColorsScheme scheme) {
return ((MyColorScheme)scheme).isReadOnly();
}
@@ -107,6 +107,7 @@ public class NewColorAndFontPanel extends JPanel {
optionsPanel.addListener(new ColorAndFontSettingsListener.Abstract() {
@Override
public void settingsChanged() {
mySchemesPanel.updateOnCurrentSettingsChange();
optionsPanel.applyChangesToScheme();
previewPanel.updateView();
}
@@ -107,7 +107,13 @@ public abstract class AbstractSchemeActions<T extends Scheme> {
public void update(AnActionEvent e) {
Presentation p = e.getPresentation();
T scheme = getCurrentScheme();
p.setEnabled(scheme != null && mySchemesPanel.getModel().canResetScheme(scheme));
if(scheme != null && mySchemesPanel.getModel().canResetScheme(scheme)) {
p.setVisible(true);
p.setEnabled(mySchemesPanel.getModel().differsFromDefault(scheme));
}
else {
p.setEnabledAndVisible(false);
}
}
}
@@ -133,4 +133,8 @@ public abstract class AbstractSchemesPanel<T extends Scheme> extends JPanel {
@NotNull
public abstract SchemesModel<T> getModel();
public void updateOnCurrentSettingsChange() {
mySchemesCombo.updateSelected();
}
}
@@ -45,6 +45,7 @@ public class SchemesCombo<T extends Scheme> {
private AbstractSchemesPanel<T> mySchemesPanel;
private final CardLayout myLayout;
private final JTextField myNameEditorField;
private final MyComboBoxModel myComboBoxModel;
private final static KeyStroke ESC_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
private final static KeyStroke ENTER_KEY_STROKE = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
@@ -53,6 +54,7 @@ public class SchemesCombo<T extends Scheme> {
mySchemesPanel = schemesPanel;
myLayout = new CardLayout();
myRootPanel = new JPanel(myLayout);
myComboBoxModel = new MyComboBoxModel();
createCombo();
myRootPanel.add(myComboBox);
myNameEditorField = createNameEditorField();
@@ -76,6 +78,10 @@ public class SchemesCombo<T extends Scheme> {
}, ENTER_KEY_STROKE, JComponent.WHEN_FOCUSED);
return nameEditorField;
}
public void updateSelected() {
myComboBox.repaint();
}
private void stopEdit() {
String newName = myNameEditorField.getText();
@@ -105,7 +111,7 @@ public class SchemesCombo<T extends Scheme> {
}
private void createCombo() {
myComboBox = new ComboBox<>();
myComboBox = new ComboBox<>(myComboBoxModel);
myComboBox.setRenderer(new MyListCellRenderer());
myComboBox.addActionListener(new ActionListener() {
@Override
@@ -113,15 +119,6 @@ public class SchemesCombo<T extends Scheme> {
mySchemesPanel.getActions().onSchemeChanged(getSelectedScheme());
}
});
myComboBox.setModel(new DefaultComboBoxModel<MySchemeListItem<T>>() {
@Override
public void setSelectedItem(Object anObject) {
if (anObject instanceof MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) {
return;
}
super.setSelectedItem(anObject);
}
});
}
public void startEdit() {
@@ -134,19 +131,24 @@ public class SchemesCombo<T extends Scheme> {
}
private SimpleTextAttributes getSchemeAttributes(@NotNull MySchemeListItem<T> item) {
SchemesModel<T> model = mySchemesPanel.getModel();
T scheme = item.getScheme();
return scheme != null && mySchemesPanel.getModel().canDeleteScheme(scheme)
SimpleTextAttributes baseAttributes = scheme !=null && model.canDeleteScheme(scheme)
? SimpleTextAttributes.REGULAR_ATTRIBUTES
: SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
if (scheme != null && model.canResetScheme(scheme) && model.differsFromDefault(scheme)) {
return baseAttributes.derive(-1, JBColor.BLUE, null, null);
}
return baseAttributes;
}
public void resetSchemes(@NotNull Collection<T> schemes) {
myComboBox.removeAllItems();
myComboBoxModel.removeAllElements();
SchemesModel<T> model = mySchemesPanel.getModel();
if (model.supportsProjectSchemes()) {
myComboBox.addItem(new MySeparatorItem(PROJECT_LEVEL));
myComboBoxModel.addElement(new MySeparatorItem(PROJECT_LEVEL));
addItems(schemes, scheme -> model.isProjectScheme(scheme));
myComboBox.addItem(new MySeparatorItem(IDE_LEVEL));
myComboBoxModel.addElement(new MySeparatorItem(IDE_LEVEL));
addItems(schemes, scheme -> !model.isProjectScheme(scheme));
}
else {
@@ -157,7 +159,7 @@ public class SchemesCombo<T extends Scheme> {
private void addItems(@NotNull Collection<T> schemes, Function<T,Boolean> filter) {
for (T scheme : schemes) {
if (filter.apply(scheme)) {
myComboBox.addItem(new MySchemeListItem<>(scheme));
myComboBoxModel.addElement(new MySchemeListItem<>(scheme));
}
}
}
@@ -297,4 +299,15 @@ public class SchemesCombo<T extends Scheme> {
}
return null;
}
private class MyComboBoxModel extends DefaultComboBoxModel<MySchemeListItem<T>> {
@Override
public void setSelectedItem(Object anObject) {
if (anObject instanceof MySchemeListItem && ((MySchemeListItem)anObject).isSeparator()) {
return;
}
super.setSelectedItem(anObject);
}
}
}
@@ -32,4 +32,6 @@ public interface SchemesModel<T extends Scheme> {
boolean canRenameScheme(@NotNull T scheme);
boolean nameExists(@NotNull String name);
boolean differsFromDefault(@NotNull T scheme);
}
@@ -128,7 +128,7 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Pers
return false;
}
return scheme.isEqualToBundled(bundledScheme);
return scheme.equals(bundledScheme);
}
@Override
@@ -16,6 +16,7 @@
package com.intellij.util;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.DifferenceFilter;
import com.intellij.util.containers.ContainerUtil;
@@ -500,6 +501,26 @@ public class ReflectionUtil {
return valuesChanged;
}
public static boolean comparePublicNonFinalFields(@NotNull Object first,
@NotNull Object second) {
Set<Field> firstFields = ContainerUtil.newHashSet(first.getClass().getFields());
for (Field field : second.getClass().getFields()) {
if (firstFields.contains(field)) {
if (isPublic(field) && !isFinal(field)) {
try {
if (!Comparing.equal(field.get(first), field.get(second))) {
return false;
}
}
catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
return true;
}
public static void copyFieldValue(@NotNull Object from, @NotNull Object to, @NotNull Field field)
throws IllegalAccessException {
Class<?> fieldType = field.getType();