@Override
 public void setEditorFontName(String fontName) {
   int editorFontSize = getEditorFontSize();
   myFontPreferences.clear();
   myFontPreferences.register(fontName, editorFontSize);
   initFonts();
 }
 private static void readFontSettings(
     @NotNull Element element, @NotNull FontPreferences preferences, boolean isDefaultScheme) {
   List children = element.getChildren(OPTION_ELEMENT);
   String fontFamily = null;
   int size = -1;
   for (Object child : children) {
     Element e = (Element) child;
     if (EDITOR_FONT_NAME.equals(e.getAttributeValue(NAME_ATTR))) {
       fontFamily = getValue(e);
     } else if (EDITOR_FONT_SIZE.equals(e.getAttributeValue(NAME_ATTR))) {
       try {
         size = Integer.parseInt(getValue(e));
         if (isDefaultScheme) {
           size = JBUI.scale(size);
         }
       } catch (NumberFormatException ex) {
         // ignore
       }
     }
   }
   if (fontFamily != null && size > 1) {
     preferences.register(fontFamily, size);
   } else if (fontFamily != null) {
     preferences.addFontFamily(fontFamily);
   }
 }
 @NotNull
 public static FontInfo getFontAbleToDisplay(
     int codePoint, @JdkConstants.FontStyle int style, @NotNull FontPreferences preferences) {
   boolean tryDefaultFont = true;
   List<String> fontFamilies = preferences.getEffectiveFontFamilies();
   FontInfo result;
   //noinspection ForLoopReplaceableByForEach
   for (int i = 0, len = fontFamilies.size();
       i < len;
       ++i) { // avoid foreach, it instantiates ArrayList$Itr, this traversal happens very often
     final String fontFamily = fontFamilies.get(i);
     result =
         doGetFontAbleToDisplay(codePoint, preferences.getSize(fontFamily), style, fontFamily);
     if (result != null) {
       return result;
     }
     tryDefaultFont &= !FontPreferences.DEFAULT_FONT_NAME.equals(fontFamily);
   }
   int size = FontPreferences.DEFAULT_FONT_SIZE;
   if (!fontFamilies.isEmpty()) {
     size = preferences.getSize(fontFamilies.get(0));
   }
   if (tryDefaultFont) {
     result = doGetFontAbleToDisplay(codePoint, size, style, FontPreferences.DEFAULT_FONT_NAME);
     if (result != null) {
       return result;
     }
   }
   result = doGetFontAbleToDisplay(codePoint, size, style);
   if (LOG.isDebugEnabled()) {
     LOG.debug("Fallback font: " + result.getFont().getFontName());
   }
   return result;
 }
 @Override
 public int getConsoleFontSize() {
   String font = getConsoleFontName();
   UISettings uiSettings = UISettings.getInstance();
   if ((uiSettings == null || !uiSettings.PRESENTATION_MODE)
       && myConsoleFontPreferences.hasSize(font)) {
     return myConsoleFontPreferences.getSize(font);
   }
   return getEditorFontSize();
 }
  private void readScheme(Element node) {
    myDeprecatedBackgroundColor = null;
    if (!SCHEME_ELEMENT.equals(node.getName())) {
      return;
    }

    setName(node.getAttributeValue(NAME_ATTR));
    int readVersion = Integer.parseInt(node.getAttributeValue(VERSION_ATTR, "0"));
    if (readVersion > CURR_VERSION) {
      throw new IllegalStateException("Unsupported color scheme version: " + readVersion);
    }

    myVersion = readVersion;
    String isDefaultScheme = node.getAttributeValue(DEFAULT_SCHEME_ATTR);
    boolean isDefault = isDefaultScheme != null && Boolean.parseBoolean(isDefaultScheme);
    if (!isDefault) {
      myParentScheme =
          DefaultColorSchemesManager.getInstance()
              .getScheme(node.getAttributeValue(PARENT_SCHEME_ATTR, DEFAULT_SCHEME_NAME));
    }

    for (final Object o : node.getChildren()) {
      Element childNode = (Element) o;
      String childName = childNode.getName();
      if (OPTION_ELEMENT.equals(childName)) {
        readSettings(childNode, isDefault);
      } else if (EDITOR_FONT.equals(childName)) {
        readFontSettings(childNode, myFontPreferences, isDefault);
      } else if (CONSOLE_FONT.equals(childName)) {
        readFontSettings(childNode, myConsoleFontPreferences, isDefault);
      } else if (COLORS_ELEMENT.equals(childName)) {
        readColors(childNode);
      } else if (ATTRIBUTES_ELEMENT.equals(childName)) {
        readAttributes(childNode);
      }
    }

    if (myDeprecatedBackgroundColor != null) {
      TextAttributes textAttributes = myAttributesMap.get(HighlighterColors.TEXT);
      if (textAttributes == null) {
        textAttributes =
            new TextAttributes(
                Color.black, myDeprecatedBackgroundColor, null, EffectType.BOXED, Font.PLAIN);
        myAttributesMap.put(HighlighterColors.TEXT, textAttributes);
      } else {
        textAttributes.setBackgroundColor(myDeprecatedBackgroundColor);
      }
    }

    if (myConsoleFontPreferences.getEffectiveFontFamilies().isEmpty()) {
      myFontPreferences.copyTo(myConsoleFontPreferences);
    }

    initFonts();
  }
  /**
   * Called on editor settings change. Current model is expected to drop all cached information
   * about the settings if any.
   */
  public void reinitSettings() {
    boolean softWrapsUsedBefore = myUseSoftWraps;
    myUseSoftWraps = areSoftWrapsEnabledInEditor();

    int tabWidthBefore = myTabWidth;
    myTabWidth = EditorUtil.getTabSize(myEditor);

    boolean fontsChanged = false;
    if (!myFontPreferences.equals(myEditor.getColorsScheme().getFontPreferences())
        && myEditorTextRepresentationHelper instanceof DefaultEditorTextRepresentationHelper) {
      fontsChanged = true;
      myEditor.getColorsScheme().getFontPreferences().copyTo(myFontPreferences);
      ((DefaultEditorTextRepresentationHelper) myEditorTextRepresentationHelper)
          .clearSymbolWidthCache();
      myPainter.reinit();
    }

    if ((myUseSoftWraps ^ softWrapsUsedBefore)
        || (tabWidthBefore >= 0 && myTabWidth != tabWidthBefore)
        || fontsChanged) {
      myApplianceManager.reset();
      myDeferredFoldRegions.clear();
      myStorage.removeAll();
      myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
    }
  }
 @Override
 public String getEditorFontName() {
   if (myFallbackFontName != null) {
     return myFallbackFontName;
   }
   return myFontPreferences.getFontFamily();
 }
  protected void initFonts() {
    String editorFontName = getEditorFontName();
    int editorFontSize = getEditorFontSize();

    myFallbackFontName =
        FontPreferences.getFallbackName(editorFontName, editorFontSize, myParentScheme);
    if (myFallbackFontName != null) {
      editorFontName = myFallbackFontName;
    }
    Font plainFont = new Font(editorFontName, Font.PLAIN, editorFontSize);
    Font boldFont = new Font(editorFontName, Font.BOLD, editorFontSize);
    Font italicFont = new Font(editorFontName, Font.ITALIC, editorFontSize);
    Font boldItalicFont = new Font(editorFontName, Font.BOLD | Font.ITALIC, editorFontSize);

    myFonts.put(EditorFontType.PLAIN, plainFont);
    myFonts.put(EditorFontType.BOLD, boldFont);
    myFonts.put(EditorFontType.ITALIC, italicFont);
    myFonts.put(EditorFontType.BOLD_ITALIC, boldItalicFont);

    String consoleFontName = getConsoleFontName();
    int consoleFontSize = getConsoleFontSize();

    Font consolePlainFont = new Font(consoleFontName, Font.PLAIN, consoleFontSize);
    Font consoleBoldFont = new Font(consoleFontName, Font.BOLD, consoleFontSize);
    Font consoleItalicFont = new Font(consoleFontName, Font.ITALIC, consoleFontSize);
    Font consoleBoldItalicFont =
        new Font(consoleFontName, Font.BOLD | Font.ITALIC, consoleFontSize);

    myFonts.put(EditorFontType.CONSOLE_PLAIN, consolePlainFont);
    myFonts.put(EditorFontType.CONSOLE_BOLD, consoleBoldFont);
    myFonts.put(EditorFontType.CONSOLE_ITALIC, consoleItalicFont);
    myFonts.put(EditorFontType.CONSOLE_BOLD_ITALIC, consoleBoldItalicFont);
  }
  private static void writeFontPreferences(
      @NotNull String key, @NotNull Element parent, @NotNull FontPreferences preferences) {
    for (String fontFamily : preferences.getRealFontFamilies()) {
      Element element = new Element(key);
      Element e = new Element(OPTION_ELEMENT);
      e.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
      e.setAttribute(VALUE_ELEMENT, fontFamily);
      element.addContent(e);

      e = new Element(OPTION_ELEMENT);
      e.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
      e.setAttribute(VALUE_ELEMENT, String.valueOf(preferences.getSize(fontFamily)));
      element.addContent(e);

      parent.addContent(element);
    }
  }
  public void copyTo(AbstractColorsScheme newScheme) {
    myFontPreferences.copyTo(newScheme.myFontPreferences);
    newScheme.myLineSpacing = myLineSpacing;
    newScheme.myQuickDocFontSize = myQuickDocFontSize;
    myConsoleFontPreferences.copyTo(newScheme.myConsoleFontPreferences);
    newScheme.myConsoleLineSpacing = myConsoleLineSpacing;

    final Set<EditorFontType> types = myFonts.keySet();
    for (EditorFontType type : types) {
      Font font = myFonts.get(type);
      newScheme.setFont(type, font);
    }

    newScheme.myAttributesMap = new HashMap<TextAttributesKey, TextAttributes>(myAttributesMap);
    newScheme.myColorsMap = new HashMap<ColorKey, Color>(myColorsMap);
    newScheme.myVersion = myVersion;
  }
    protected void initFonts() {
      String consoleFontName = getConsoleFontName();
      int consoleFontSize = getConsoleFontSize();
      myFontPreferences.clear();
      myFontPreferences.register(consoleFontName, consoleFontSize);

      myFontsMap = new EnumMap<EditorFontType, Font>(EditorFontType.class);

      Font plainFont = new Font(consoleFontName, Font.PLAIN, consoleFontSize);
      Font boldFont = new Font(consoleFontName, Font.BOLD, consoleFontSize);
      Font italicFont = new Font(consoleFontName, Font.ITALIC, consoleFontSize);
      Font boldItalicFont = new Font(consoleFontName, Font.BOLD | Font.ITALIC, consoleFontSize);

      myFontsMap.put(EditorFontType.PLAIN, plainFont);
      myFontsMap.put(EditorFontType.BOLD, boldFont);
      myFontsMap.put(EditorFontType.ITALIC, italicFont);
      myFontsMap.put(EditorFontType.BOLD_ITALIC, boldItalicFont);
    }
 protected AbstractColorsScheme(EditorColorsScheme parentScheme) {
   myParentScheme = parentScheme;
   myFontPreferences.setChangeListener(
       new Runnable() {
         @Override
         public void run() {
           initFonts();
         }
       });
 }
  @Override
  public void updateOptionsList() {
    myIsInSchemeChange = true;

    myLineSpacingField.setText(Float.toString(getLineSpacing()));
    FontPreferences fontPreferences = getFontPreferences();
    List<String> fontFamilies = fontPreferences.getEffectiveFontFamilies();
    myPrimaryCombo.setFontName(fontPreferences.getFontFamily());
    boolean isThereSecondaryFont = fontFamilies.size() > 1;
    myUseSecondaryFontCheckbox.setSelected(isThereSecondaryFont);
    mySecondaryCombo.setFontName(isThereSecondaryFont ? fontFamilies.get(1) : null);
    myEditorFontSizeField.setText(
        String.valueOf(fontPreferences.getSize(fontPreferences.getFontFamily())));

    boolean readOnly = ColorAndFontOptions.isReadOnly(myOptions.getSelectedScheme());
    myPrimaryCombo.setEnabled(!readOnly);
    mySecondaryCombo.setEnabled(isThereSecondaryFont && !readOnly);
    myOnlyMonospacedCheckBox.setEnabled(!readOnly);
    myLineSpacingField.setEnabled(!readOnly);
    myEditorFontSizeField.setEnabled(!readOnly);
    myUseSecondaryFontCheckbox.setEnabled(!readOnly);

    myEnableLigaturesCheckbox.setEnabled(!readOnly);
    myLigaturesInfoLinkLabel.setEnabled(!readOnly);
    myEnableLigaturesCheckbox.setSelected(fontPreferences.useLigatures());

    myIsInSchemeChange = false;
  }
 private void syncFontFamilies() {
   if (myIsInSchemeChange) {
     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);
     }
     fontPreferences.register(primaryFontFamily, JBUI.scale(fontSize));
   }
   if (secondaryFontFamily != null) {
     if (!FontPreferences.DEFAULT_FONT_NAME.equals(secondaryFontFamily)) {
       fontPreferences.addFontFamily(secondaryFontFamily);
     }
     fontPreferences.register(secondaryFontFamily, JBUI.scale(fontSize));
   }
   updateDescription(true);
 }
 @Override
 public void setConsoleFontSize(int fontSize) {
   myConsoleFontPreferences.register(getConsoleFontName(), fontSize);
   initFonts();
 }
 @Override
 public void setConsoleFontName(String fontName) {
   int consoleFontSize = getConsoleFontSize();
   myConsoleFontPreferences.clear();
   myConsoleFontPreferences.register(fontName, consoleFontSize);
 }
 @Override
 public String getConsoleFontName() {
   return myConsoleFontPreferences.getFontFamily();
 }
 @Override
 public int getEditorFontSize() {
   return myFontPreferences.getSize(getEditorFontName());
 }
 @Override
 public void setEditorFontSize(int fontSize) {
   myFontPreferences.register(getEditorFontName(), fontSize);
   initFonts();
 }
 @Override
 public void setConsoleFontPreferences(@NotNull FontPreferences preferences) {
   preferences.copyTo(myFontPreferences);
   initFonts();
 }
  public void writeExternal(Element parentNode) throws WriteExternalException {
    parentNode.setAttribute(NAME_ATTR, getName());
    parentNode.setAttribute(VERSION_ATTR, Integer.toString(myVersion));

    if (myParentScheme != null) {
      parentNode.setAttribute(PARENT_SCHEME_ATTR, myParentScheme.getName());
    }

    Element element = new Element(OPTION_ELEMENT);
    element.setAttribute(NAME_ATTR, LINE_SPACING);
    element.setAttribute(VALUE_ELEMENT, String.valueOf(getLineSpacing()));
    parentNode.addContent(element);

    // IJ has used a 'single customizable font' mode for ages. That's why we want to support that
    // format now, when it's possible
    // to specify fonts sequence (see getFontPreferences()), there are big chances that many clients
    // still will use a single font.
    // That's why we want to use old format when zero or one font is selected and 'extended' format
    // otherwise.
    boolean useOldFontFormat = myFontPreferences.getEffectiveFontFamilies().size() <= 1;
    if (useOldFontFormat) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_FONT_SIZE);
      element.setAttribute(VALUE_ELEMENT, String.valueOf(getEditorFontSize() / JBUI.scale(1)));
      parentNode.addContent(element);
    } else {
      writeFontPreferences(EDITOR_FONT, parentNode, myFontPreferences);
    }

    if (!myFontPreferences.equals(myConsoleFontPreferences)) {
      if (myConsoleFontPreferences.getEffectiveFontFamilies().size() <= 1) {
        element = new Element(OPTION_ELEMENT);
        element.setAttribute(NAME_ATTR, CONSOLE_FONT_NAME);
        element.setAttribute(VALUE_ELEMENT, getConsoleFontName());
        parentNode.addContent(element);

        if (getConsoleFontSize() != getEditorFontSize()) {
          element = new Element(OPTION_ELEMENT);
          element.setAttribute(NAME_ATTR, CONSOLE_FONT_SIZE);
          element.setAttribute(
              VALUE_ELEMENT, Integer.toString(getConsoleFontSize() / JBUI.scale(1)));
          parentNode.addContent(element);
        }
      } else {
        writeFontPreferences(CONSOLE_FONT, parentNode, myConsoleFontPreferences);
      }
    }

    if (getConsoleLineSpacing() != getLineSpacing()) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, CONSOLE_LINE_SPACING);
      element.setAttribute(VALUE_ELEMENT, Float.toString(getConsoleLineSpacing()));
      parentNode.addContent(element);
    }

    if (DEFAULT_FONT_SIZE != getQuickDocFontSize()) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_QUICK_JAVADOC_FONT_SIZE);
      element.setAttribute(VALUE_ELEMENT, getQuickDocFontSize().toString());
      parentNode.addContent(element);
    }

    if (useOldFontFormat) {
      element = new Element(OPTION_ELEMENT);
      element.setAttribute(NAME_ATTR, EDITOR_FONT_NAME);
      element.setAttribute(VALUE_ELEMENT, getEditorFontName());
      parentNode.addContent(element);
    }

    Element colorElements = new Element(COLORS_ELEMENT);
    Element attrElements = new Element(ATTRIBUTES_ELEMENT);

    writeColors(colorElements);
    writeAttributes(attrElements);

    if (colorElements.getChildren().size() > 0) {
      parentNode.addContent(colorElements);
    }
    if (attrElements.getChildren().size() > 0) {
      parentNode.addContent(attrElements);
    }
  }