From 2b515b4bb58fc04c3f716147f74069ecf969dd82 Mon Sep 17 00:00:00 2001 From: Rustam Vishnyakov Date: Tue, 28 Feb 2017 17:50:17 +0300 Subject: [PATCH] 1) Separated FontPreferences interface and implementation 2) Added a flag to inherit console font preferences from editor ones 3) Moved line spacing to FontPreferences Other fixes according to [CR-IC-7467] --- .../colors/DelegatingFontPreferences.java | 84 ++++++ .../editor/colors/EditorColorsScheme.java | 3 + .../editor/colors/FontPreferences.java | 234 +++------------ .../colors/ModifiableFontPreferences.java | 33 +++ .../colors/impl/AbstractColorsScheme.java | 95 ++++--- .../colors/impl/FontPreferencesImpl.java | 267 ++++++++++++++++++ .../options/colors/ColorAndFontOptions.java | 26 +- .../options/colors/ConsoleFontOptions.java | 17 +- .../options/colors/FontOptions.java | 86 ++++-- .../options/colors/NewColorAndFontPanel.java | 28 -- .../codeInsight/lookup/impl/LookupImpl.java | 3 +- .../openapi/editor/impl/EditorImpl.java | 7 +- .../editor/impl/SoftWrapModelImpl.java | 4 +- .../JBTerminalSystemSettingsProviderBase.java | 3 +- .../editor/colors/FontPreferencesTest.java | 5 +- .../impl/EditorColorsSchemeImplTest.java | 59 ++-- .../impl/EditorColorsSchemeDelegateTest.java | 4 +- .../editor/EditorColorSchemeTestCase.java | 27 ++ 18 files changed, 651 insertions(+), 334 deletions(-) create mode 100644 platform/editor-ui-api/src/com/intellij/openapi/editor/colors/DelegatingFontPreferences.java create mode 100644 platform/editor-ui-api/src/com/intellij/openapi/editor/colors/ModifiableFontPreferences.java create mode 100644 platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/FontPreferencesImpl.java diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/DelegatingFontPreferences.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/DelegatingFontPreferences.java new file mode 100644 index 000000000000..b3425258650b --- /dev/null +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/DelegatingFontPreferences.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2017 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.openapi.editor.colors; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class DelegatingFontPreferences implements FontPreferences { + private FontPreferences myDelegate; + + public DelegatingFontPreferences(FontPreferences delegate) { + myDelegate = delegate; + } + + @NotNull + @Override + public List getEffectiveFontFamilies() { + return myDelegate.getEffectiveFontFamilies(); + } + + @NotNull + @Override + public List getRealFontFamilies() { + return myDelegate.getRealFontFamilies(); + } + + @NotNull + @Override + public String getFontFamily() { + return myDelegate.getFontFamily(); + } + + @Override + public int getSize(@NotNull String fontFamily) { + return myDelegate.getSize(fontFamily); + } + + @Override + public void copyTo(@NotNull FontPreferences preferences) { + myDelegate.copyTo(preferences); + } + + @Override + public boolean useLigatures() { + return myDelegate.useLigatures(); + } + + @Override + public boolean hasSize(@NotNull String fontName) { + return myDelegate.hasSize(fontName); + } + + @Override + public float getLineSpacing() { + return myDelegate.getLineSpacing(); + } + + @Override + public void setLineSpacing(float lineSpacing) { + myDelegate.setLineSpacing(lineSpacing); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DelegatingFontPreferences) { + return myDelegate.equals(((DelegatingFontPreferences)obj).myDelegate); + } + return false; + } +} diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java index aeed76a146cd..1c03ce24419b 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/EditorColorsScheme.java @@ -99,6 +99,9 @@ public interface EditorColorsScheme extends Cloneable, TextAttributesScheme, Sch @NotNull FontPreferences getConsoleFontPreferences(); void setConsoleFontPreferences(@NotNull FontPreferences preferences); + + default void setUseEditorFontPreferencesInConsole() {} + default boolean isUseEditorFontPreferencesInConsole() {return false;} String getConsoleFontName(); void setConsoleFontName(String fontName); diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java index 044a2deab404..76cb55b0e6d4 100644 --- a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/FontPreferences.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2016 JetBrains s.r.o. + * Copyright 2000-2017 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. @@ -17,8 +17,6 @@ package com.intellij.openapi.editor.colors; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.util.SystemInfo; -import com.intellij.util.containers.ContainerUtilRt; -import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,190 +24,32 @@ import org.jetbrains.annotations.Nullable; import java.awt.*; import java.util.List; -/** - * Utility class which holds collection of font families and theirs sizes. - *

- * The basic idea is to allow end-user to configure not a single font but fonts list instead - every time particular font is unable - * to display particular char, next font is tried. This is an improvement over an old approach when it was possible to configure - * only a single font family. Fallback fonts were chosen randomly when that font family was unable to display particular char then. - * - * @author Denis Zhdanov - * @since 12/20/12 9:37 PM - */ -public class FontPreferences { +public interface FontPreferences { + @NonNls @NotNull String DEFAULT_FONT_NAME = getDefaultFontName(); + int DEFAULT_FONT_SIZE = FontSize.SMALL.getSize(); - @NonNls @NotNull public static final String DEFAULT_FONT_NAME = getDefaultFontName(); - public static final int DEFAULT_FONT_SIZE = FontSize.SMALL.getSize(); - - @NotNull private final TObjectIntHashMap myFontSizes = new TObjectIntHashMap<>(); - @NotNull private final List myEffectiveFontFamilies = ContainerUtilRt.newArrayList(); - @NotNull private final List myRealFontFamilies = ContainerUtilRt.newArrayList(); - - private boolean myUseLigatures; - - @Nullable private Runnable myChangeListener; - - /** - * Font size to use by default. Default value is {@link #DEFAULT_FONT_SIZE}. - */ - private int myTemplateFontSize = DEFAULT_FONT_SIZE; - - public void setChangeListener(@Nullable Runnable changeListener) { - myChangeListener = changeListener; - } - - @Nullable - public Runnable getChangeListener() { - return myChangeListener; - } - - public void clear() { - myEffectiveFontFamilies.clear(); - myRealFontFamilies.clear(); - myFontSizes.clear(); - if (myChangeListener != null) { - myChangeListener.run(); - } - } - - public void clearFonts() { - myEffectiveFontFamilies.clear(); - myRealFontFamilies.clear(); - if (myChangeListener != null) { - myChangeListener.run(); - } - } - - public boolean hasSize(@NotNull String fontName) { - return myFontSizes.containsKey(fontName); - } - - public int getSize(@NotNull String fontFamily) { - int result = myFontSizes.get(fontFamily); - if (result <= 0) { - result = myTemplateFontSize; - } - return result > 0 ? result : DEFAULT_FONT_SIZE; - } - - public void setSize(@NotNull String fontFamily, int size) { - myFontSizes.put(fontFamily, size); - myTemplateFontSize = size; - if (myChangeListener != null) { - myChangeListener.run(); - } - } - - /** - * This method might return results different from {@link #getRealFontFamilies()} when - * {@link #getFallbackName(String, int, EditorColorsScheme) a font family unavailable at current environment} - * has been {@link #register(String, int) registered} at the current font preferences object. - *

- * Effective fonts will hold fallback values for such font families then (exposed by the current method), 'real fonts' will - * be available via {@link #getRealFontFamilies()}. - * - * @return effective font families to use - */ - @NotNull - public List getEffectiveFontFamilies() { - return myEffectiveFontFamilies; - } - - /** - * @return 'real' font families - * @see #getEffectiveFontFamilies() - */ - @NotNull - public List getRealFontFamilies() { - return myRealFontFamilies; - } - - public void register(@NotNull String fontFamily, int size) { - String fallbackFontFamily = getFallbackName(fontFamily, size, null); - if (!myRealFontFamilies.contains(fontFamily)) { - myRealFontFamilies.add(fontFamily); - } - String effectiveFontFamily = fallbackFontFamily == null ? fontFamily : fallbackFontFamily; - if (!myEffectiveFontFamilies.contains(effectiveFontFamily)) { - myEffectiveFontFamilies.add(effectiveFontFamily); - } - setSize(fontFamily, size); - } - - /** - * @return first element of the {@link #getEffectiveFontFamilies() registered font families} (if any); - * {@link #DEFAULT_FONT_NAME} otherwise - */ - @NotNull - public String getFontFamily() { - return myEffectiveFontFamilies.isEmpty() ? DEFAULT_FONT_NAME : myEffectiveFontFamilies.get(0); - } - - public void addFontFamily(@NotNull String fontFamily) { - String fallbackFontFamily = getFallbackName(fontFamily, DEFAULT_FONT_SIZE, null); - if (!myRealFontFamilies.contains(fontFamily)) { - myRealFontFamilies.add(fontFamily); - } - String effectiveFontFamily = fallbackFontFamily == null ? fontFamily : fallbackFontFamily; - if (!myEffectiveFontFamilies.contains(effectiveFontFamily)) { - myEffectiveFontFamilies.add(effectiveFontFamily); - } - if (myChangeListener != null) { - myChangeListener.run(); - } - } - - public void copyTo(@NotNull final FontPreferences preferences) { - preferences.myEffectiveFontFamilies.clear(); - preferences.myEffectiveFontFamilies.addAll(myEffectiveFontFamilies); - preferences.myRealFontFamilies.clear(); - preferences.myRealFontFamilies.addAll(myRealFontFamilies); - preferences.myFontSizes.clear(); - preferences.myTemplateFontSize = myTemplateFontSize; - for (String fontFamily : myRealFontFamilies) { - if (myFontSizes.containsKey(fontFamily)) { - preferences.myFontSizes.put(fontFamily, myFontSizes.get(fontFamily)); - } - } - preferences.myUseLigatures = myUseLigatures; - } - - @Override - public int hashCode() { - return myRealFontFamilies.hashCode(); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - FontPreferences that = (FontPreferences)o; - - if (!myRealFontFamilies.equals(that.myRealFontFamilies)) return false; - for (String fontFamily : myRealFontFamilies) { - if (myFontSizes.get(fontFamily) != that.myFontSizes.get(fontFamily)) { - return false; - } - } - - if (myUseLigatures != that.myUseLigatures) return false; - - return true; - } + float DEFAULT_LINE_SPACING = 1.0f; @NotNull - private static String getDefaultFontName() { - if (SystemInfo.isMacOSSnowLeopard) return "Menlo"; - if (SystemInfo.isXWindow && !GraphicsEnvironment.isHeadless()) { - for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) { - if ("DejaVu Sans Mono".equals(font.getName())) { - return font.getFontName(); - } - } - } - return "Monospaced"; - } + List getEffectiveFontFamilies(); + + @NotNull + List getRealFontFamilies(); + + @NotNull + String getFontFamily(); + + int getSize(@NotNull String fontFamily); + + void copyTo(@NotNull FontPreferences preferences); + + boolean useLigatures(); + + boolean hasSize(@NotNull String fontName); + + float getLineSpacing(); + + void setLineSpacing(float lineSpacing); /** * There is a possible case that particular font family is not available at particular environment (e.g. Monaco under *nix). @@ -225,29 +65,23 @@ public class FontPreferences { * null if font family with the given name is registered at the current environment */ @Nullable - public static String getFallbackName(@NotNull String fontName, int fontSize, @Nullable EditorColorsScheme fallbackScheme) { + static String getFallbackName(@NotNull String fontName, int fontSize, @Nullable EditorColorsScheme fallbackScheme) { Font plainFont = new Font(fontName, Font.PLAIN, fontSize); if (plainFont.getFamily().equals("Dialog") && !("Dialog".equals(fontName) || fontName.startsWith("Dialog."))) { return fallbackScheme == null ? DEFAULT_FONT_NAME : fallbackScheme.getEditorFontName(); } return null; } - - public boolean useLigatures() { - return myUseLigatures; - } - - public void setUseLigatures(boolean useLigatures) { - if (useLigatures != myUseLigatures) { - myUseLigatures = useLigatures; - if (myChangeListener != null) { - myChangeListener.run(); + + static String getDefaultFontName() { + if (SystemInfo.isMacOSSnowLeopard) return "Menlo"; + if (SystemInfo.isXWindow && !GraphicsEnvironment.isHeadless()) { + for (Font font : GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts()) { + if ("DejaVu Sans Mono".equals(font.getName())) { + return font.getFontName(); + } } } - } - - @Override - public String toString() { - return "Effective font families: " + myEffectiveFontFamilies; + return "Monospaced"; } } diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/ModifiableFontPreferences.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/ModifiableFontPreferences.java new file mode 100644 index 000000000000..914b8f4c8036 --- /dev/null +++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/colors/ModifiableFontPreferences.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2017 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.openapi.editor.colors; + +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public interface ModifiableFontPreferences extends FontPreferences { + void clear(); + void clearFonts(); + void setUseLigatures(boolean useLigatures); + void addFontFamily(String family); + void register(String family, int size); + void setEffectiveFontFamilies(List fontFamilies); + void setRealFontFamilies(List fontFamilies); + void setTemplateFontSize(int size); + void resetFontSizes(); + void setFontSize(@NotNull String fontFamily, int size); +} diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java index c0ba5adbe121..561e7782c715 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java @@ -62,18 +62,15 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial protected EditorColorsScheme myParentScheme; protected FontSize myQuickDocFontSize = DEFAULT_FONT_SIZE; - protected float myLineSpacing; @NotNull private final Map myFonts = new EnumMap<>(EditorFontType.class); - @NotNull private final FontPreferences myFontPreferences = new FontPreferences(); - @NotNull private final FontPreferences myConsoleFontPreferences = new FontPreferences(); + @NotNull private FontPreferencesImpl myFontPreferences = new FontPreferencesImpl(); + @NotNull private FontPreferences myConsoleFontPreferences = new DelegatingFontPreferences(myFontPreferences); private final ValueElementReader myValueReader = new TextAttributesReader(); private String myFallbackFontName; private String mySchemeName; - private float myConsoleLineSpacing = -1; - private boolean myIsSaveNeeded; private boolean myCanBeDeleted = true; @@ -173,10 +170,13 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial public void copyTo(AbstractColorsScheme newScheme) { myFontPreferences.copyTo(newScheme.myFontPreferences); - newScheme.myLineSpacing = myLineSpacing; newScheme.myQuickDocFontSize = myQuickDocFontSize; - myConsoleFontPreferences.copyTo(newScheme.myConsoleFontPreferences); - newScheme.myConsoleLineSpacing = myConsoleLineSpacing; + if (myConsoleFontPreferences instanceof DelegatingFontPreferences) { + newScheme.setUseEditorFontPreferencesInConsole(); + } + else { + newScheme.setConsoleFontPreferences(myConsoleFontPreferences); + } final Set types = myFonts.keySet(); for (EditorFontType type : types) { @@ -214,7 +214,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial @Override public void setLineSpacing(float lineSpacing) { - myLineSpacing = EditorFontsConstants.checkAndFixEditorLineSpacing(lineSpacing); + myFontPreferences.setLineSpacing(lineSpacing); } @Override @@ -265,8 +265,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial @Override public float getLineSpacing() { - float spacing = myLineSpacing; - return spacing <= 0 ? 1.0f : spacing; + return myFontPreferences.getLineSpacing(); } protected void initFonts() { @@ -355,10 +354,10 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial readSettings(childNode, isDefault, fontScale); break; case EDITOR_FONT: - readFontSettings(childNode, myFontPreferences, isDefault, fontScale.get()); + myFontPreferences = readFontSettings(childNode, isDefault, fontScale.get()); break; case CONSOLE_FONT: - readFontSettings(childNode, myConsoleFontPreferences, isDefault, fontScale.get()); + myConsoleFontPreferences = readFontSettings(childNode, isDefault, fontScale.get()); break; case COLORS_ELEMENT: readColors(childNode); @@ -474,7 +473,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial } case LINE_SPACING: { Float value = myValueReader.read(Float.class, childNode); - if (value != null) myLineSpacing = value; + if (value != null) setLineSpacing(value); break; } case EDITOR_FONT_SIZE: { @@ -514,7 +513,9 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial } case CONSOLE_LIGATURES: { Boolean value = myValueReader.read(Boolean.class, childNode); - if (value != null) myConsoleFontPreferences.setUseLigatures(value); + if (value != null) { + ensureEditableConsoleFontPreferences().setUseLigatures(value); + } break; } } @@ -531,11 +532,11 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial return (int)JBUI.scale(size); } - private void readFontSettings(@NotNull Element element, - @NotNull FontPreferences preferences, - boolean isDefaultScheme, - @Nullable Float fontScale) - { + private FontPreferencesImpl readFontSettings(@NotNull Element element, + boolean isDefaultScheme, + @Nullable Float fontScale) { + FontPreferencesImpl preferences = new FontPreferencesImpl(); + preferences.setChangeListener(() -> initFonts()); List children = element.getChildren(OPTION_ELEMENT); String fontFamily = null; int size = -1; @@ -554,6 +555,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial else if (fontFamily != null) { preferences.addFontFamily(fontFamily); } + return preferences; } public void writeExternal(Element parentNode) { @@ -579,7 +581,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial parentNode.addContent(metaInfoToElement()); } - if (getLineSpacing() != 1) { + if (getLineSpacing() != FontPreferences.DEFAULT_LINE_SPACING) { JdomKt.addOptionTag(parentNode, LINE_SPACING, String.valueOf(getLineSpacing())); } @@ -595,7 +597,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial } writeLigaturesPreferences(parentNode, myFontPreferences, EDITOR_LIGATURES); - if (!myFontPreferences.equals(myConsoleFontPreferences)) { + if (!(myConsoleFontPreferences instanceof DelegatingFontPreferences)) { if (myConsoleFontPreferences.getEffectiveFontFamilies().size() <= 1) { JdomKt.addOptionTag(parentNode, CONSOLE_FONT_NAME, getConsoleFontName()); @@ -607,10 +609,9 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial writeFontPreferences(CONSOLE_FONT, parentNode, myConsoleFontPreferences); } writeLigaturesPreferences(parentNode, myConsoleFontPreferences, CONSOLE_LIGATURES); - } - - if (getConsoleLineSpacing() != getLineSpacing()) { - JdomKt.addOptionTag(parentNode, CONSOLE_LINE_SPACING, Float.toString(getConsoleLineSpacing())); + if (getConsoleLineSpacing() != FontPreferences.DEFAULT_LINE_SPACING) { + JdomKt.addOptionTag(parentNode, CONSOLE_LINE_SPACING, Float.toString(getConsoleLineSpacing())); + } } if (DEFAULT_FONT_SIZE != getQuickDocFontSize()) { @@ -766,10 +767,21 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial public FontPreferences getConsoleFontPreferences() { return myConsoleFontPreferences; } + + @Override + public void setUseEditorFontPreferencesInConsole() { + myConsoleFontPreferences = new DelegatingFontPreferences(myFontPreferences); + initFonts(); + } + + @Override + public boolean isUseEditorFontPreferencesInConsole() { + return myConsoleFontPreferences instanceof DelegatingFontPreferences; + } @Override public void setConsoleFontPreferences(@NotNull FontPreferences preferences) { - preferences.copyTo(myConsoleFontPreferences); + preferences.copyTo(ensureEditableConsoleFontPreferences()); initFonts(); } @@ -778,11 +790,21 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial return myConsoleFontPreferences.getFontFamily(); } + private ModifiableFontPreferences ensureEditableConsoleFontPreferences() { + if (!(myConsoleFontPreferences instanceof ModifiableFontPreferences)) { + ModifiableFontPreferences editablePrefs = new FontPreferencesImpl(); + myConsoleFontPreferences.copyTo(editablePrefs); + myConsoleFontPreferences = editablePrefs; + } + return (ModifiableFontPreferences)myConsoleFontPreferences; + } + @Override public void setConsoleFontName(String fontName) { + ModifiableFontPreferences consolePreferences = ensureEditableConsoleFontPreferences(); int consoleFontSize = getConsoleFontSize(); - myConsoleFontPreferences.clear(); - myConsoleFontPreferences.register(fontName, consoleFontSize); + consolePreferences.clear(); + consolePreferences.register(fontName, consoleFontSize); } @Override @@ -797,23 +819,20 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial @Override public void setConsoleFontSize(int fontSize) { + ModifiableFontPreferences consoleFontPreferences = ensureEditableConsoleFontPreferences(); fontSize = EditorFontsConstants.checkAndFixEditorFontSize(fontSize); - myConsoleFontPreferences.register(getConsoleFontName(), fontSize); + consoleFontPreferences.register(getConsoleFontName(), fontSize); initFonts(); } @Override public float getConsoleLineSpacing() { - float consoleLineSpacing = myConsoleLineSpacing; - if (consoleLineSpacing == -1) { - return getLineSpacing(); - } - return consoleLineSpacing; + return myConsoleFontPreferences.getLineSpacing(); } @Override public void setConsoleLineSpacing(float lineSpacing) { - myConsoleLineSpacing = lineSpacing; + myConsoleFontPreferences.setLineSpacing(lineSpacing); } protected TextAttributes getFallbackAttributes(@NotNull TextAttributesKey fallbackKey) { @@ -916,9 +935,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial } } - return getLineSpacing() == otherScheme.getLineSpacing() && - getConsoleLineSpacing() == otherScheme.getConsoleLineSpacing() && - myFontPreferences.equals(otherScheme.getFontPreferences()) && + return myFontPreferences.equals(otherScheme.getFontPreferences()) && myConsoleFontPreferences.equals(otherScheme.getConsoleFontPreferences()) && attributesEqual(otherScheme) && colorsEqual(otherScheme) && diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/FontPreferencesImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/FontPreferencesImpl.java new file mode 100644 index 000000000000..0c5f2cf30c38 --- /dev/null +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/FontPreferencesImpl.java @@ -0,0 +1,267 @@ +/* + * Copyright 2000-2017 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.openapi.editor.colors.impl; + +import com.intellij.application.options.EditorFontsConstants; +import com.intellij.openapi.editor.colors.EditorColorsScheme; +import com.intellij.openapi.editor.colors.FontPreferences; +import com.intellij.openapi.editor.colors.ModifiableFontPreferences; +import com.intellij.util.containers.ContainerUtilRt; +import gnu.trove.TObjectIntHashMap; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * Utility class which holds collection of font families and theirs sizes. + *

+ * The basic idea is to allow end-user to configure not a single font but fonts list instead - every time particular font is unable + * to display particular char, next font is tried. This is an improvement over an old approach when it was possible to configure + * only a single font family. Fallback fonts were chosen randomly when that font family was unable to display particular char then. + * + * @author Denis Zhdanov + * @since 12/20/12 9:37 PM + */ +public class FontPreferencesImpl implements ModifiableFontPreferences { + + @NotNull private final TObjectIntHashMap myFontSizes = new TObjectIntHashMap<>(); + @NotNull private final List myEffectiveFontFamilies = ContainerUtilRt.newArrayList(); + @NotNull private final List myRealFontFamilies = ContainerUtilRt.newArrayList(); + + private boolean myUseLigatures; + private float myLineSpacing = DEFAULT_LINE_SPACING; + + @Nullable private Runnable myChangeListener; + + /** + * Font size to use by default. Default value is {@link #DEFAULT_FONT_SIZE}. + */ + private int myTemplateFontSize = DEFAULT_FONT_SIZE; + + public void setChangeListener(@Nullable Runnable changeListener) { + myChangeListener = changeListener; + } + + @Nullable + public Runnable getChangeListener() { + return myChangeListener; + } + + @Override + public void clear() { + myEffectiveFontFamilies.clear(); + myRealFontFamilies.clear(); + myFontSizes.clear(); + if (myChangeListener != null) { + myChangeListener.run(); + } + } + + @Override + public void clearFonts() { + myEffectiveFontFamilies.clear(); + myRealFontFamilies.clear(); + if (myChangeListener != null) { + myChangeListener.run(); + } + } + + @Override + public boolean hasSize(@NotNull String fontName) { + return myFontSizes.containsKey(fontName); + } + + @Override + public float getLineSpacing() { + return myLineSpacing; + } + + @Override + public void setLineSpacing(float lineSpacing) { + myLineSpacing = EditorFontsConstants.checkAndFixEditorLineSpacing(lineSpacing); + } + + public int getSize(@NotNull String fontFamily) { + int result = myFontSizes.get(fontFamily); + if (result <= 0) { + result = myTemplateFontSize; + } + return result > 0 ? result : DEFAULT_FONT_SIZE; + } + + public void setSize(@NotNull String fontFamily, int size) { + myFontSizes.put(fontFamily, size); + myTemplateFontSize = size; + if (myChangeListener != null) { + myChangeListener.run(); + } + } + + /** + * This method might return results different from {@link #getRealFontFamilies()} when + * {@link #getFallbackName(String, int, EditorColorsScheme) a font family unavailable at current environment} + * has been {@link #register(String, int) registered} at the current font preferences object. + *

+ * Effective fonts will hold fallback values for such font families then (exposed by the current method), 'real fonts' will + * be available via {@link #getRealFontFamilies()}. + * + * @return effective font families to use + */ + @Override + @NotNull + public List getEffectiveFontFamilies() { + return myEffectiveFontFamilies; + } + + /** + * @return 'real' font families + * @see #getEffectiveFontFamilies() + */ + @Override + @NotNull + public List getRealFontFamilies() { + return myRealFontFamilies; + } + + @Override + public void register(@NotNull String fontFamily, int size) { + String fallbackFontFamily = FontPreferences.getFallbackName(fontFamily, size, null); + if (!myRealFontFamilies.contains(fontFamily)) { + myRealFontFamilies.add(fontFamily); + } + String effectiveFontFamily = fallbackFontFamily == null ? fontFamily : fallbackFontFamily; + if (!myEffectiveFontFamilies.contains(effectiveFontFamily)) { + myEffectiveFontFamilies.add(effectiveFontFamily); + } + setSize(fontFamily, size); + } + + /** + * @return first element of the {@link #getEffectiveFontFamilies() registered font families} (if any); + * {@link #DEFAULT_FONT_NAME} otherwise + */ + @Override + @NotNull + public String getFontFamily() { + return myEffectiveFontFamilies.isEmpty() ? DEFAULT_FONT_NAME : myEffectiveFontFamilies.get(0); + } + + @Override + public void addFontFamily(@NotNull String fontFamily) { + String fallbackFontFamily = FontPreferences.getFallbackName(fontFamily, DEFAULT_FONT_SIZE, null); + if (!myRealFontFamilies.contains(fontFamily)) { + myRealFontFamilies.add(fontFamily); + } + String effectiveFontFamily = fallbackFontFamily == null ? fontFamily : fallbackFontFamily; + if (!myEffectiveFontFamilies.contains(effectiveFontFamily)) { + myEffectiveFontFamilies.add(effectiveFontFamily); + } + if (myChangeListener != null) { + myChangeListener.run(); + } + } + + @Override + public void copyTo(@NotNull final FontPreferences preferences) { + if (preferences instanceof ModifiableFontPreferences) { + ModifiableFontPreferences modifiablePreferences = (ModifiableFontPreferences)preferences; + modifiablePreferences.setEffectiveFontFamilies(myEffectiveFontFamilies); + modifiablePreferences.setRealFontFamilies(myRealFontFamilies); + modifiablePreferences.setTemplateFontSize(myTemplateFontSize); + modifiablePreferences.resetFontSizes(); + for (String fontFamily : myRealFontFamilies) { + if (myFontSizes.containsKey(fontFamily)) { + modifiablePreferences.setFontSize(fontFamily, myFontSizes.get(fontFamily)); + } + } + modifiablePreferences.setUseLigatures(myUseLigatures); + modifiablePreferences.setLineSpacing(myLineSpacing); + } + } + + @Override + public void resetFontSizes() { + myFontSizes.clear(); + } + + @Override + public void setFontSize(@NotNull String fontFamily, int size) { + myFontSizes.put(fontFamily, size); + } + + @Override + public void setTemplateFontSize(int size) { + myTemplateFontSize = size; + } + + @Override + public void setEffectiveFontFamilies(@NotNull List fontFamilies) { + myEffectiveFontFamilies.clear(); + myEffectiveFontFamilies.addAll(fontFamilies); + } + + @Override + public void setRealFontFamilies(@NotNull List fontFamilies) { + myRealFontFamilies.clear(); + myRealFontFamilies.addAll(fontFamilies); + } + + @Override + public int hashCode() { + return myRealFontFamilies.hashCode(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FontPreferencesImpl that = (FontPreferencesImpl)o; + + if (!myRealFontFamilies.equals(that.myRealFontFamilies)) return false; + for (String fontFamily : myRealFontFamilies) { + if (myFontSizes.get(fontFamily) != that.myFontSizes.get(fontFamily)) { + return false; + } + } + + if (myUseLigatures != that.myUseLigatures) return false; + if (myLineSpacing != that.myLineSpacing) return false; + + return true; + } + + @Override + public boolean useLigatures() { + return myUseLigatures; + } + + @Override + public void setUseLigatures(boolean useLigatures) { + if (useLigatures != myUseLigatures) { + myUseLigatures = useLigatures; + if (myChangeListener != null) { + myChangeListener.run(); + } + } + } + + @Override + public String toString() { + return "Effective font families: " + myEffectiveFontFamilies; + } +} diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java index 40a01e241a13..215a15ffa8d4 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java @@ -1089,9 +1089,13 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract super(parentScheme); parentScheme.getFontPreferences().copyTo(getFontPreferences()); - setLineSpacing(parentScheme.getLineSpacing()); - parentScheme.getConsoleFontPreferences().copyTo(getConsoleFontPreferences()); + if (parentScheme.isUseEditorFontPreferencesInConsole()) { + setUseEditorFontPreferencesInConsole(); + } + else { + setConsoleFontPreferences(parentScheme.getConsoleFontPreferences()); + } setConsoleLineSpacing(parentScheme.getConsoleLineSpacing()); setQuickDocFontSize(parentScheme.getQuickDocFontSize()); @@ -1146,14 +1150,11 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract } private boolean isFontModified() { - if (!getFontPreferences().equals(myParentScheme.getFontPreferences())) return true; - if (getLineSpacing() != myParentScheme.getLineSpacing()) return true; - return getQuickDocFontSize() != myParentScheme.getQuickDocFontSize(); + return !getFontPreferences().equals(myParentScheme.getFontPreferences()); } private boolean isConsoleFontModified() { - if (!getConsoleFontPreferences().equals(myParentScheme.getConsoleFontPreferences())) return true; - return getConsoleLineSpacing() != myParentScheme.getConsoleLineSpacing(); + return !getConsoleFontPreferences().equals(myParentScheme.getConsoleFontPreferences()); } private boolean apply() { @@ -1167,10 +1168,13 @@ public class ColorAndFontOptions extends SearchableConfigurable.Parent.Abstract boolean isModified = isFontModified() || isConsoleFontModified(); scheme.setFontPreferences(getFontPreferences()); - scheme.setLineSpacing(myLineSpacing); - scheme.setQuickDocFontSize(getQuickDocFontSize()); - scheme.setConsoleFontPreferences(getConsoleFontPreferences()); - scheme.setConsoleLineSpacing(getConsoleLineSpacing()); + + if (isUseEditorFontPreferencesInConsole()) { + scheme.setUseEditorFontPreferencesInConsole(); + } + else { + scheme.setConsoleFontPreferences(getConsoleFontPreferences()); + } for (EditorSchemeAttributeDescriptor descriptor : myDescriptors) { if (descriptor.isModified()) { diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java index cddae4aa4527..a3ecb00c9048 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/ConsoleFontOptions.java @@ -15,6 +15,7 @@ */ package com.intellij.application.options.colors; +import com.intellij.openapi.editor.colors.DelegatingFontPreferences; import com.intellij.openapi.editor.colors.FontPreferences; import org.jetbrains.annotations.NotNull; @@ -23,7 +24,7 @@ import org.jetbrains.annotations.NotNull; */ public class ConsoleFontOptions extends FontOptions { public ConsoleFontOptions(ColorAndFontOptions options) { - super(options); + super(options, "Use editor font preferences"); } @NotNull @@ -32,6 +33,20 @@ public class ConsoleFontOptions extends FontOptions { return getCurrentScheme().getConsoleFontPreferences(); } + @Override + protected void setDelegatingPreferences(boolean isDelegating) { + FontPreferences currPrefs = getCurrentScheme().getConsoleFontPreferences(); + if (currPrefs instanceof DelegatingFontPreferences == isDelegating) return; + if (isDelegating) { + getCurrentScheme().setUseEditorFontPreferencesInConsole(); + } + else { + getCurrentScheme().setConsoleFontPreferences(getFontPreferences()); + } + updateOptionsList(); + updateDescription(true); + } + @Override protected void setFontSize(int fontSize) { getCurrentScheme().setConsoleFontSize(fontSize); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java index 851e4a54f0b2..cd2ca0dd8802 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java @@ -21,9 +21,7 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.IdeTooltipManager; import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.FontPreferences; +import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.util.SystemInfo; import com.intellij.ui.DocumentAdapter; @@ -40,10 +38,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.event.DocumentEvent; import java.awt.*; -import java.awt.event.ActionListener; -import java.awt.event.ItemListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; +import java.awt.event.*; import java.util.HashSet; import java.util.List; import java.util.Locale; @@ -67,21 +62,44 @@ public class FontOptions extends JPanel implements OptionsPanel{ private final JCheckBox myUseSecondaryFontCheckbox = new JCheckBox(ApplicationBundle.message("secondary.font")); private final JCheckBox myEnableLigaturesCheckbox = new JCheckBox(ApplicationBundle.message("use.ligatures")); private final FontComboBox mySecondaryCombo = new FontComboBox(false, false); + + private final JCheckBox myInheritFontCheckbox; @NotNull private final JBCheckBox myOnlyMonospacedCheckBox = new JBCheckBox(ApplicationBundle.message("checkbox.show.only.monospaced.fonts")); private boolean myIsInSchemeChange; + private JLabel myPrimaryLabel; + private JLabel mySizeLabel; public FontOptions(@NotNull ColorAndFontOptions options) { + this(options, null); + } + + public FontOptions(@NotNull ColorAndFontOptions options, @Nullable String inheritFontTitle) { setLayout(new MigLayout("ins 0, gap 5, flowx")); myOptions = options; + myInheritFontCheckbox = inheritFontTitle != null ? new JCheckBox(inheritFontTitle) : null; + if (myInheritFontCheckbox != null) { + add(myInheritFontCheckbox, "newline, sx 2"); + myInheritFontCheckbox.setSelected(getFontPreferences() instanceof DelegatingFontPreferences); + myInheritFontCheckbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + setDelegatingPreferences(myInheritFontCheckbox.isSelected()); + } + }); + add(new JSeparator(), "newline, growx, span"); + } + add(myOnlyMonospacedCheckBox, "newline 10, sgx b, sx 2"); - add(new JLabel(ApplicationBundle.message("primary.font")), "newline, ax right"); + myPrimaryLabel = new JLabel(ApplicationBundle.message("primary.font")); + add(myPrimaryLabel, "newline, ax right"); add(myPrimaryCombo, "sgx b"); - add(new JLabel(ApplicationBundle.message("editbox.font.size")), "gapleft 20"); + mySizeLabel = new JLabel(ApplicationBundle.message("editbox.font.size")); + add(mySizeLabel, "gapleft 20"); add(myEditorFontSizeField); add(new JLabel(ApplicationBundle.message("editbox.line.spacing")), "gapleft 20"); add(myLineSpacingField); @@ -187,11 +205,17 @@ public class FontOptions extends JPanel implements OptionsPanel{ } }); myEnableLigaturesCheckbox.addActionListener(e -> { - getFontPreferences().setUseLigatures(myEnableLigaturesCheckbox.isSelected()); - updateDescription(true); + FontPreferences preferences = getFontPreferences(); + if (preferences instanceof ModifiableFontPreferences) { + ((ModifiableFontPreferences)preferences).setUseLigatures(myEnableLigaturesCheckbox.isSelected()); + updateDescription(true); + } }); } + protected void setDelegatingPreferences(boolean isDelegating) { + } + private int getFontSizeFromField() { try { return Math.min(EditorFontsConstants.getMaxEditorFontSize(), @@ -231,23 +255,26 @@ public class FontOptions extends JPanel implements OptionsPanel{ return; } FontPreferences fontPreferences = getFontPreferences(); - fontPreferences.clearFonts(); - String primaryFontFamily = myPrimaryCombo.getFontName(); - String secondaryFontFamily = mySecondaryCombo.isEnabled() ? mySecondaryCombo.getFontName() : null; - int fontSize = getFontSizeFromField(); - if (primaryFontFamily != null ) { - if (!FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) { - fontPreferences.addFontFamily(primaryFontFamily); + if (fontPreferences instanceof ModifiableFontPreferences) { + ModifiableFontPreferences modifiableFontPreferences = (ModifiableFontPreferences)fontPreferences; + modifiableFontPreferences.clearFonts(); + String primaryFontFamily = myPrimaryCombo.getFontName(); + String secondaryFontFamily = mySecondaryCombo.isEnabled() ? mySecondaryCombo.getFontName() : null; + int fontSize = getFontSizeFromField(); + if (primaryFontFamily != null) { + if (!FontPreferences.DEFAULT_FONT_NAME.equals(primaryFontFamily)) { + modifiableFontPreferences.addFontFamily(primaryFontFamily); + } + modifiableFontPreferences.register(primaryFontFamily, fontSize); } - fontPreferences.register(primaryFontFamily, fontSize); - } - if (secondaryFontFamily != null) { - if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)){ - fontPreferences.addFontFamily(secondaryFontFamily); + if (secondaryFontFamily != null) { + if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)) { + modifiableFontPreferences.addFontFamily(secondaryFontFamily); + } + modifiableFontPreferences.register(secondaryFontFamily, fontSize); } - fontPreferences.register(secondaryFontFamily, fontSize); + updateDescription(true); } - updateDescription(true); } @Override @@ -263,12 +290,19 @@ public class FontOptions extends JPanel implements OptionsPanel{ mySecondaryCombo.setFontName(isThereSecondaryFont ? fontFamilies.get(1) : null); myEditorFontSizeField.setText(String.valueOf(fontPreferences.getSize(fontPreferences.getFontFamily()))); - boolean readOnly = ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme()); + boolean isReadOnlyColorScheme = ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme()); + if (myInheritFontCheckbox != null) { + myInheritFontCheckbox.setEnabled(!isReadOnlyColorScheme); + myInheritFontCheckbox.setSelected(myOptions.getSelectedScheme().getConsoleFontPreferences() instanceof DelegatingFontPreferences); + } + boolean readOnly = isReadOnlyColorScheme || !(getFontPreferences() instanceof ModifiableFontPreferences); myPrimaryCombo.setEnabled(!readOnly); + myPrimaryLabel.setEnabled(!readOnly); mySecondaryCombo.setEnabled(isThereSecondaryFont && !readOnly); myOnlyMonospacedCheckBox.setEnabled(!readOnly); myLineSpacingField.setEnabled(!readOnly); myEditorFontSizeField.setEnabled(!readOnly); + mySizeLabel.setEnabled(!readOnly); myUseSecondaryFontCheckbox.setEnabled(!readOnly); myEnableLigaturesCheckbox.setEnabled(!readOnly && SystemInfo.isJetbrainsJvm); diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java b/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java index 4367db63e518..151d171d8979 100644 --- a/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java +++ b/platform/lang-impl/src/com/intellij/application/options/colors/NewColorAndFontPanel.java @@ -16,9 +16,7 @@ package com.intellij.application.options.colors; -import com.intellij.openapi.application.ApplicationBundle; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.EditorSchemeAttributeDescriptor; import com.intellij.openapi.options.colors.ColorSettingsPage; import com.intellij.openapi.ui.MessageType; @@ -43,7 +41,6 @@ public class NewColorAndFontPanel extends JPanel { private final SchemesPanel mySchemesPanel; private final OptionsPanel myOptionsPanel; private final PreviewPanel myPreviewPanel; - private final AbstractAction myCopyAction; private final String myCategory; private final Collection myOptionList; @@ -63,26 +60,6 @@ public class NewColorAndFontPanel extends JPanel { top.add(mySchemesPanel, BorderLayout.NORTH); top.add(myOptionsPanel.getPanel(), BorderLayout.CENTER); - if (optionsPanel instanceof ConsoleFontOptions) { - JPanel wrapper = new JPanel(new FlowLayout(FlowLayout.TRAILING)); - myCopyAction = new AbstractAction(ApplicationBundle.message("action.apply.editor.font.settings")) { - @Override - public void actionPerformed(ActionEvent e) { - EditorColorsScheme scheme = ((ConsoleFontOptions)myOptionsPanel).getCurrentScheme(); - scheme.setConsoleFontName(scheme.getEditorFontName()); - scheme.setConsoleFontPreferences(scheme.getFontPreferences()); - scheme.setConsoleFontSize(scheme.getEditorFontSize()); - scheme.setConsoleLineSpacing(scheme.getLineSpacing()); - myOptionsPanel.updateOptionsList(); - myPreviewPanel.updateView(); - } - }; - wrapper.add(new JButton(myCopyAction)); - top.add(wrapper, BorderLayout.SOUTH); - } - else { - myCopyAction = null; - } // We don't want to show non-used preview panel (it's considered to be not in use if it doesn't contain text). if (myPreviewPanel.getPanel() != null && (page == null || !StringUtil.isEmptyOrSpaces(page.getDemoText()))) { @@ -125,11 +102,6 @@ public class NewColorAndFontPanel extends JPanel { public void schemeChanged(final Object source) { myOptionsPanel.updateOptionsList(); myPreviewPanel.updateView(); - if (optionsPanel instanceof ConsoleFontOptions) { - ConsoleFontOptions options = (ConsoleFontOptions)optionsPanel; - boolean readOnly = ColorAndFontOptions.isReadOnly(options.getCurrentScheme()); - myCopyAction.setEnabled(!readOnly); - } } }); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index b7501f3f6a75..beb8c4c5c38c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -36,6 +36,7 @@ import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.FontPreferences; +import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.editor.event.DocumentAdapter; import com.intellij.openapi.project.Project; @@ -108,7 +109,7 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable private PrefixChangeListener myPrefixChangeListener = new PrefixChangeListener.Adapter() {}; private final LookupPreview myPreview = new LookupPreview(this); // keeping our own copy of editor's font preferences, which can be used in non-EDT threads (to avoid race conditions) - private final FontPreferences myFontPreferences = new FontPreferences(); + private final FontPreferences myFontPreferences = new FontPreferencesImpl(); private long myStampShown = 0; private boolean myShown = false; diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 982c2fc61794..0e80d04f7707 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -41,6 +41,7 @@ import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.*; import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.colors.impl.DelegateColorScheme; +import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; import com.intellij.openapi.editor.event.*; import com.intellij.openapi.editor.ex.*; import com.intellij.openapi.editor.ex.util.EditorUIUtil; @@ -3943,8 +3944,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } private class MyColorSchemeDelegate extends DelegateColorScheme { - private final FontPreferences myFontPreferences = new FontPreferences(); - private final FontPreferences myConsoleFontPreferences = new FontPreferences(); + private final FontPreferencesImpl myFontPreferences = new FontPreferencesImpl(); + private final FontPreferencesImpl myConsoleFontPreferences = new FontPreferencesImpl(); private final Map myOwnAttributes = ContainerUtilRt.newHashMap(); private final Map myOwnColors = ContainerUtilRt.newHashMap(); private final EditorColorsScheme myCustomGlobalScheme; @@ -3982,7 +3983,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi myFontsMap.put(EditorFontType.CONSOLE_BOLD_ITALIC, new Font(consoleFontName, Font.BOLD | Font.ITALIC, consoleFontSize)); } - private void updatePreferences(FontPreferences preferences, String fontName, int fontSize, FontPreferences delegatePreferences) { + private void updatePreferences(FontPreferencesImpl preferences, String fontName, int fontSize, FontPreferences delegatePreferences) { preferences.clear(); preferences.register(fontName, fontSize); if (delegatePreferences != null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java index ae2eed33fb90..3ed8cdaee216 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java @@ -21,7 +21,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Attachment; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; -import com.intellij.openapi.editor.colors.FontPreferences; +import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; import com.intellij.openapi.editor.event.DocumentEvent; import com.intellij.openapi.editor.ex.*; import com.intellij.openapi.editor.ex.util.EditorUtil; @@ -84,7 +84,7 @@ public class SoftWrapModelImpl extends InlayModel.SimpleAdapter private boolean myUseSoftWraps; private int myTabWidth = -1; - private final FontPreferences myFontPreferences = new FontPreferences(); + private final FontPreferencesImpl myFontPreferences = new FontPreferencesImpl(); /** * Soft wraps need to be kept up-to-date on all editor modification (changing text, adding/removing/expanding/collapsing fold diff --git a/platform/platform-impl/src/com/intellij/terminal/JBTerminalSystemSettingsProviderBase.java b/platform/platform-impl/src/com/intellij/terminal/JBTerminalSystemSettingsProviderBase.java index c50cd2798df8..53da54708a3c 100644 --- a/platform/platform-impl/src/com/intellij/terminal/JBTerminalSystemSettingsProviderBase.java +++ b/platform/platform-impl/src/com/intellij/terminal/JBTerminalSystemSettingsProviderBase.java @@ -23,6 +23,7 @@ import com.intellij.openapi.actionSystem.KeyboardShortcut; import com.intellij.openapi.actionSystem.Shortcut; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.colors.*; +import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.keymap.KeymapManager; @@ -151,7 +152,7 @@ public class JBTerminalSystemSettingsProviderBase extends DefaultTabbedSettingsP protected static class MyColorSchemeDelegate implements EditorColorsScheme { - private final FontPreferences myFontPreferences = new FontPreferences(); + private final FontPreferencesImpl myFontPreferences = new FontPreferencesImpl(); private final HashMap myOwnAttributes = new HashMap<>(); private final HashMap myOwnColors = new HashMap<>(); private Map myFontsMap = null; diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java index 4d1da0bc9c3c..5476fbda54f9 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java @@ -16,6 +16,7 @@ package com.intellij.openapi.editor.colors; +import com.intellij.openapi.editor.colors.impl.FontPreferencesImpl; import org.junit.Test; import java.awt.*; @@ -26,7 +27,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; public class FontPreferencesTest { - private final FontPreferences myPreferences = new FontPreferences(); + private final FontPreferencesImpl myPreferences = new FontPreferencesImpl(); @Test public void testDefaults() { @@ -100,7 +101,7 @@ public class FontPreferencesTest { namesAndSizes); // check object copying - FontPreferences preferences = new FontPreferences(); + FontPreferencesImpl preferences = new FontPreferencesImpl(); myPreferences.copyTo(preferences); // check myTemplateFontSize String fontName = "Another" + getNonExistingFontName(); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java index 62f33b347e2d..cc538de04ba2 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java @@ -17,10 +17,7 @@ package com.intellij.openapi.editor.colors.impl; import com.intellij.editor.EditorColorSchemeTestCase; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; -import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.colors.EditorColorsScheme; -import com.intellij.openapi.editor.colors.FontPreferences; -import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.editor.colors.*; import com.intellij.openapi.editor.markup.EffectType; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.util.Pair; @@ -56,13 +53,20 @@ public class EditorColorsSchemeImplTest extends EditorColorSchemeTestCase { assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getConsoleFontSize()); } - public void testSetPreferences() throws Exception { + public void testSetFontPreferences() throws Exception { String fontName1 = getExistingNonDefaultFontName(); String fontName2 = getAnotherExistingNonDefaultFontName(); - myScheme.getFontPreferences().register(fontName1, 25); - myScheme.getFontPreferences().register(fontName2, 13); - myScheme.getConsoleFontPreferences().register(fontName1, 21); - myScheme.getConsoleFontPreferences().register(fontName2, 15); + FontPreferences fontPreferences = myScheme.getFontPreferences(); + assertInstanceOf(fontPreferences, ModifiableFontPreferences.class); + ((ModifiableFontPreferences)fontPreferences).register(fontName1, 25); + ((ModifiableFontPreferences)fontPreferences).register(fontName2, 13); + FontPreferences consoleFontPreferences = myScheme.getConsoleFontPreferences(); + assertInstanceOf(consoleFontPreferences, FontPreferences.class); + myScheme.setConsoleFontSize(10); + consoleFontPreferences = myScheme.getConsoleFontPreferences(); + assertInstanceOf(consoleFontPreferences, ModifiableFontPreferences.class); + ((ModifiableFontPreferences)consoleFontPreferences).register(fontName1, 21); + ((ModifiableFontPreferences)consoleFontPreferences).register(fontName2, 15); checkState(myScheme.getFontPreferences(), Arrays.asList(fontName1, fontName2), @@ -80,6 +84,15 @@ public class EditorColorsSchemeImplTest extends EditorColorSchemeTestCase { fontName2, 15); assertEquals(fontName1, myScheme.getConsoleFontName()); assertEquals(21, myScheme.getConsoleFontSize()); + + myScheme.setUseEditorFontPreferencesInConsole(); + checkState(myScheme.getConsoleFontPreferences(), + Arrays.asList(fontName1, fontName2), + Arrays.asList(fontName1, fontName2), + fontName1, + fontName1, 25, + fontName2, 13); + } public void testSetName() throws Exception { @@ -176,24 +189,32 @@ public class EditorColorsSchemeImplTest extends EditorColorSchemeTestCase { EditorColorsScheme defaultScheme = EditorColorsManager.getInstance().getScheme(EditorColorsScheme.DEFAULT_SCHEME_NAME); EditorColorsScheme editorColorsScheme = (EditorColorsScheme)defaultScheme.clone(); editorColorsScheme.setName("test"); - Element root = new Element("scheme"); - ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); - root.removeChildren("option"); // Remove font options - root.removeChildren("metaInfo"); - assertXmlOutputEquals("", root); + assertXmlOutputEquals( + "", + serialize(editorColorsScheme)); + + String fontName = editorColorsScheme.getEditorFontName(); + + editorColorsScheme.setConsoleFontName(fontName); + editorColorsScheme.setConsoleFontSize(10); + assertXmlOutputEquals( + "\n" + + " ", + serialize(editorColorsScheme)); } public void testWriteInheritedFromDarcula() throws Exception { EditorColorsScheme darculaScheme = EditorColorsManager.getInstance().getScheme("Darcula"); EditorColorsScheme editorColorsScheme = (EditorColorsScheme)darculaScheme.clone(); editorColorsScheme.setName("test"); - Element root = new Element("scheme"); - ((AbstractColorsScheme)editorColorsScheme).writeExternal(root); - root.removeChildren("option"); // Remove font options - root.removeChildren("metaInfo"); - assertXmlOutputEquals("", root); + assertXmlOutputEquals( + "", + serialize(editorColorsScheme)); } + public void testSaveInheritance() throws Exception { Pair result = doTestWriteRead(DefaultLanguageHighlighterColors.STATIC_METHOD, USE_INHERITED_MARKER); TextAttributes fallbackAttrs = result.first.getAttributes(DefaultLanguageHighlighterColors.STATIC_METHOD.getFallbackAttributeKey()); diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorColorsSchemeDelegateTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorColorsSchemeDelegateTest.java index 4a1f716c351d..3119c8fe6a72 100644 --- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorColorsSchemeDelegateTest.java +++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorColorsSchemeDelegateTest.java @@ -18,6 +18,7 @@ package com.intellij.openapi.editor.impl; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.colors.FontPreferences; +import com.intellij.openapi.editor.colors.ModifiableFontPreferences; import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl; import com.intellij.testFramework.TestFileType; @@ -48,7 +49,8 @@ public class EditorColorsSchemeDelegateTest extends AbstractEditorTest { public void testSecondaryFontIsAvailable() throws Exception { FontPreferences globalPrefs = myTestScheme.getFontPreferences(); - globalPrefs.register("DummyFont", globalPrefs.getSize(globalPrefs.getFontFamily())); + assertInstanceOf(globalPrefs, ModifiableFontPreferences.class); + ((ModifiableFontPreferences)globalPrefs).register("DummyFont", globalPrefs.getSize(globalPrefs.getFontFamily())); assertEquals(2, globalPrefs.getRealFontFamilies().size()); init("blah", TestFileType.TEXT); diff --git a/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java b/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java index 6954b4222544..1159a7632411 100644 --- a/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java +++ b/platform/testFramework/src/com/intellij/editor/EditorColorSchemeTestCase.java @@ -38,6 +38,8 @@ import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; +import java.util.ArrayList; +import java.util.List; public abstract class EditorColorSchemeTestCase extends LightPlatformTestCase { protected static EditorColorsScheme loadScheme(@NotNull String docText) throws ParserConfigurationException, IOException, SAXException { @@ -80,4 +82,29 @@ public abstract class EditorColorSchemeTestCase extends LightPlatformTestCase { String actual = writer.toString(); assertEquals(expected, actual); } + + protected Element serialize(@NotNull EditorColorsScheme scheme) { + Element root = new Element("scheme"); + ((AbstractColorsScheme)scheme).writeExternal(root); + fixPlatformSpecificValues(root); + root.removeChildren("metaInfo"); + return root; + } + + private static void fixPlatformSpecificValues(@NotNull Element root) { + List fontOptions = new ArrayList<>(root.getChildren("option")); + for (Element option : fontOptions) { + String name = option.getAttributeValue("name"); + if (name != null) { + if ("FONT_SCALE".equals(name) || + "EDITOR_FONT_SIZE".equals(name) || + "EDITOR_FONT_NAME".equals(name)) { + root.removeContent(option); + } + else if ("CONSOLE_FONT_NAME".equals(name)) { + option.setAttribute("value", "Test"); + } + } + } + } }