@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;
  }
 @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;
 }
  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();
  }
  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);
    }
  }