<commit_before>// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.ui.laf;

import com.intellij.CommonBundle;
import com.intellij.diagnostic.Activity;
import com.intellij.diagnostic.StartUpMeasurer;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.WelcomeWizardUtil;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.ui.*;
import com.intellij.ide.ui.laf.darcula.DarculaInstaller;
import com.intellij.ide.ui.laf.darcula.DarculaLaf;
import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl;
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.util.PopupUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.popup.OurHeavyWeightPopup;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.EventDispatcher;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ObjectUtils;
import com.intellij.util.concurrency.SynchronizedClearableLazy;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.*;
import org.intellij.lang.annotations.JdkConstants;
import org.jdom.Element;
import org.jetbrains.annotations.*;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator;
import java.util.List;
import java.util.*;
import java.util.function.BooleanSupplier;

@State(name = "LafManager", storages = @Storage(value = "laf.xml", roamingType = RoamingType.PER_OS))
public final class LafManagerImpl extends LafManager implements PersistentStateComponent<Element>, Disposable {
  private static final Logger LOG = Logger.getInstance(LafManager.class);

  @NonNls private static final String ELEMENT_LAF = "laf";
  @NonNls private static final String ATTRIBUTE_CLASS_NAME = "class-name";
  @NonNls private static final String ATTRIBUTE_THEME_NAME = "themeId";

  private static final String DEFAULT_LIGHT_THEME_ID = "JetBrainsLightTheme";
  private static final String DARCULA_EDITOR_THEME_KEY = "Darcula.SavedEditorTheme";
  private static final String DEFAULT_EDITOR_THEME_KEY = "Default.SavedEditorTheme";

  @NonNls private static final String[] ourPatchableFontResources = {"Button.font", "ToggleButton.font", "RadioButton.font",
    "CheckBox.font", "ColorChooser.font", "ComboBox.font", "Label.font", "List.font", "MenuBar.font", "MenuItem.font",
    "MenuItem.acceleratorFont", "RadioButtonMenuItem.font", "CheckBoxMenuItem.font", "Menu.font", "PopupMenu.font", "OptionPane.font",
    "Panel.font", "ProgressBar.font", "ScrollPane.font", "Viewport.font", "TabbedPane.font", "Table.font", "TableHeader.font",
    "TextField.font", "FormattedTextField.font", "Spinner.font", "PasswordField.font", "TextArea.font", "TextPane.font", "EditorPane.font",
    "TitledBorder.font", "ToolBar.font", "ToolTip.font", "Tree.font"};

  @NonNls private static final String[] ourFileChooserTextKeys = {"FileChooser.viewMenuLabelText", "FileChooser.newFolderActionLabelText",
    "FileChooser.listViewActionLabelText", "FileChooser.detailsViewActionLabelText", "FileChooser.refreshActionLabelText"};

  private final EventDispatcher<LafManagerListener> myEventDispatcher = EventDispatcher.create(LafManagerListener.class);

  private final SynchronizedClearableLazy<List<UIManager.LookAndFeelInfo>> myLaFs = new SynchronizedClearableLazy<>(() -> {
    Activity activity = StartUpMeasurer.startActivity("compute LaF list");
    List<UIManager.LookAndFeelInfo> infos = computeLafList();
    activity.end();
    return infos;
  });

  private final UIManager.LookAndFeelInfo myDefaultLightTheme = getDefaultLightTheme();
  private final UIManager.LookAndFeelInfo myDefaultDarkTheme = new DarculaLookAndFeelInfo();
  private final UIDefaults ourDefaults = (UIDefaults)UIManager.getDefaults().clone();

  private UIManager.LookAndFeelInfo myCurrentLaf;
  private final Map<UIManager.LookAndFeelInfo, HashMap<String, Object>> myStoredDefaults = new HashMap<>();

  // A constant from Mac OS X implementation. See CPlatformWindow.WINDOW_ALPHA
  public static final String WINDOW_ALPHA = "Window.alpha";

  private static final Map<String, String> ourLafClassesAliases = new HashMap<>();

  private CollectionComboBoxModel<LafReference> myLafComboBoxModel;

  static {
    ourLafClassesAliases.put("idea.dark.laf.classname", DarculaLookAndFeelInfo.CLASS_NAME);
  }

  private boolean myFirstSetup = true;
  private boolean myUpdatingPlugin = false;
  private final Set<String> myThemesInUpdatedPlugin = new HashSet<>();

  private static UIManager.LookAndFeelInfo getDefaultLightTheme() {
    for(UIThemeProvider provider: UIThemeProvider.EP_NAME.getExtensionList()) {
      if (DEFAULT_LIGHT_THEME_ID.equals(provider.id)) {
        UITheme theme = provider.createTheme();
        if (theme != null) {
          return new UIThemeBasedLookAndFeelInfo(theme);
        }
      }
    }
    LOG.error("Can't load " + DEFAULT_LIGHT_THEME_ID);
    return new IntelliJLookAndFeelInfo();
  }

  @NotNull
  private List<UIManager.LookAndFeelInfo> computeLafList() {
    List<UIManager.LookAndFeelInfo> lafList = new ArrayList<>();
    lafList.add(myDefaultLightTheme);
    lafList.add(myDefaultDarkTheme);

    if (!SystemInfo.isMac) {
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
        String name = laf.getName();
        if (!"Metal".equalsIgnoreCase(name)
            && !"CDE/Motif".equalsIgnoreCase(name)
            && !"Nimbus".equalsIgnoreCase(name)
            && !name.startsWith("Windows")
            && !"GTK+".equalsIgnoreCase(name)
            && !name.startsWith("JGoodies")) {
          lafList.add(laf);
        }
      }
    }

    LafProvider.EP_NAME.forEachExtensionSafe(provider -> {
      lafList.add(provider.getLookAndFeelInfo());
    });

    UIThemeProvider.EP_NAME.forEachExtensionSafe(provider -> {
      if (!DEFAULT_LIGHT_THEME_ID.equals(provider.id)) {
        UITheme theme = provider.createTheme();
        if (theme != null) {
          lafList.add(new UIThemeBasedLookAndFeelInfo(theme));
        }
      }
    });
    sortThemes(lafList);
    return lafList;
  }

  private static void sortThemes(@NotNull List<UIManager.LookAndFeelInfo> list) {
    list.sort((t1, t2) -> t1.getName().compareToIgnoreCase(t2.getName()));
  }

  @Override
  public void addLafManagerListener(@NotNull LafManagerListener listener) {
    myEventDispatcher.addListener(listener);
  }

  @Override
  public void addLafManagerListener(@NotNull LafManagerListener listener, @NotNull Disposable disposable) {
    ApplicationManager.getApplication().getMessageBus().connect(disposable).subscribe(LafManagerListener.TOPIC, listener);
  }

  @Override<commit_msg>IDEA-228866 Prearrange default themes<commit_after>// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.ui.laf;

import com.intellij.CommonBundle;
import com.intellij.diagnostic.Activity;
import com.intellij.diagnostic.StartUpMeasurer;
import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.WelcomeWizardUtil;
import com.intellij.ide.plugins.DynamicPluginListener;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.ui.*;
import com.intellij.ide.ui.laf.darcula.DarculaInstaller;
import com.intellij.ide.ui.laf.darcula.DarculaLaf;
import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl;
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.util.PopupUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.*;
import com.intellij.ui.popup.OurHeavyWeightPopup;
import com.intellij.ui.scale.JBUIScale;
import com.intellij.util.EventDispatcher;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ObjectUtils;
import com.intellij.util.concurrency.SynchronizedClearableLazy;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.*;
import org.intellij.lang.annotations.JdkConstants;
import org.jdom.Element;
import org.jetbrains.annotations.*;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;
import javax.swing.plaf.UIResource;
import javax.swing.plaf.metal.DefaultMetalTheme;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.text.DefaultEditorKit;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.TextAttribute;
import java.text.AttributedCharacterIterator;
import java.util.List;
import java.util.*;
import java.util.function.BooleanSupplier;

@State(name = "LafManager", storages = @Storage(value = "laf.xml", roamingType = RoamingType.PER_OS))
public final class LafManagerImpl extends LafManager implements PersistentStateComponent<Element>, Disposable {
  private static final Logger LOG = Logger.getInstance(LafManager.class);

  @NonNls private static final String ELEMENT_LAF = "laf";
  @NonNls private static final String ATTRIBUTE_CLASS_NAME = "class-name";
  @NonNls private static final String ATTRIBUTE_THEME_NAME = "themeId";

  private static final String DEFAULT_LIGHT_THEME_ID = "JetBrainsLightTheme";
  private static final String DARCULA_EDITOR_THEME_KEY = "Darcula.SavedEditorTheme";
  private static final String DEFAULT_EDITOR_THEME_KEY = "Default.SavedEditorTheme";

  @NonNls private static final String[] ourPatchableFontResources = {"Button.font", "ToggleButton.font", "RadioButton.font",
    "CheckBox.font", "ColorChooser.font", "ComboBox.font", "Label.font", "List.font", "MenuBar.font", "MenuItem.font",
    "MenuItem.acceleratorFont", "RadioButtonMenuItem.font", "CheckBoxMenuItem.font", "Menu.font", "PopupMenu.font", "OptionPane.font",
    "Panel.font", "ProgressBar.font", "ScrollPane.font", "Viewport.font", "TabbedPane.font", "Table.font", "TableHeader.font",
    "TextField.font", "FormattedTextField.font", "Spinner.font", "PasswordField.font", "TextArea.font", "TextPane.font", "EditorPane.font",
    "TitledBorder.font", "ToolBar.font", "ToolTip.font", "Tree.font"};

  @NonNls private static final String[] ourFileChooserTextKeys = {"FileChooser.viewMenuLabelText", "FileChooser.newFolderActionLabelText",
    "FileChooser.listViewActionLabelText", "FileChooser.detailsViewActionLabelText", "FileChooser.refreshActionLabelText"};

  private final EventDispatcher<LafManagerListener> myEventDispatcher = EventDispatcher.create(LafManagerListener.class);

  private final SynchronizedClearableLazy<List<UIManager.LookAndFeelInfo>> myLaFs = new SynchronizedClearableLazy<>(() -> {
    Activity activity = StartUpMeasurer.startActivity("compute LaF list");
    List<UIManager.LookAndFeelInfo> infos = computeLafList();
    activity.end();
    return infos;
  });

  private final UIManager.LookAndFeelInfo myDefaultLightTheme = getDefaultLightTheme();
  private final UIManager.LookAndFeelInfo myDefaultDarkTheme = new DarculaLookAndFeelInfo();
  private final UIDefaults ourDefaults = (UIDefaults)UIManager.getDefaults().clone();

  private UIManager.LookAndFeelInfo myCurrentLaf;
  private final Map<UIManager.LookAndFeelInfo, HashMap<String, Object>> myStoredDefaults = new HashMap<>();

  // A constant from Mac OS X implementation. See CPlatformWindow.WINDOW_ALPHA
  public static final String WINDOW_ALPHA = "Window.alpha";

  private static final Map<String, String> ourLafClassesAliases = new HashMap<>();
  private static final Map<String, Integer> lafNameOrder = new HashMap<>();

  private CollectionComboBoxModel<LafReference> myLafComboBoxModel;

  static {
    ourLafClassesAliases.put("idea.dark.laf.classname", DarculaLookAndFeelInfo.CLASS_NAME);

    lafNameOrder.put("IntelliJ Light", 0);
    lafNameOrder.put("macOS Light", 1);
    lafNameOrder.put("Windows 10 Light", 1);
    lafNameOrder.put("Darcula", 2);
    lafNameOrder.put("High contrast", 3);
  }

  private boolean myFirstSetup = true;
  private boolean myUpdatingPlugin = false;
  private final Set<String> myThemesInUpdatedPlugin = new HashSet<>();

  private static UIManager.LookAndFeelInfo getDefaultLightTheme() {
    for(UIThemeProvider provider: UIThemeProvider.EP_NAME.getExtensionList()) {
      if (DEFAULT_LIGHT_THEME_ID.equals(provider.id)) {
        UITheme theme = provider.createTheme();
        if (theme != null) {
          return new UIThemeBasedLookAndFeelInfo(theme);
        }
      }
    }
    LOG.error("Can't load " + DEFAULT_LIGHT_THEME_ID);
    return new IntelliJLookAndFeelInfo();
  }

  @NotNull
  private List<UIManager.LookAndFeelInfo> computeLafList() {
    List<UIManager.LookAndFeelInfo> lafList = new ArrayList<>();
    lafList.add(myDefaultLightTheme);
    lafList.add(myDefaultDarkTheme);

    if (!SystemInfo.isMac) {
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
        String name = laf.getName();
        if (!"Metal".equalsIgnoreCase(name)
            && !"CDE/Motif".equalsIgnoreCase(name)
            && !"Nimbus".equalsIgnoreCase(name)
            && !name.startsWith("Windows")
            && !"GTK+".equalsIgnoreCase(name)
            && !name.startsWith("JGoodies")) {
          lafList.add(laf);
        }
      }
    }

    LafProvider.EP_NAME.forEachExtensionSafe(provider -> {
      lafList.add(provider.getLookAndFeelInfo());
    });

    UIThemeProvider.EP_NAME.forEachExtensionSafe(provider -> {
      if (!DEFAULT_LIGHT_THEME_ID.equals(provider.id)) {
        UITheme theme = provider.createTheme();
        if (theme != null) {
          lafList.add(new UIThemeBasedLookAndFeelInfo(theme));
        }
      }
    });
    sortThemes(lafList);
    return lafList;
  }

  private static void sortThemes(@NotNull List<UIManager.LookAndFeelInfo> list) {
    list.sort((t1, t2) -> {
      String n1 = t1.getName();
      String n2 = t2.getName();
      if (Objects.equals(n1, n2)) return 0;

      Integer o1 = lafNameOrder.get(n1);
      Integer o2 = lafNameOrder.get(n2);
      if (o1 != null && o2 != null) return o1 - o2;
      else if (o1 != null) return -1;
      else if (o2 != null) return 1;
      else return n1.compareToIgnoreCase(n2);
    });
  }

  @Override
  public void addLafManagerListener(@NotNull LafManagerListener listener) {
    myEventDispatcher.addListener(listener);
  }

  @Override
  public void addLafManagerListener(@NotNull LafManagerListener listener, @NotNull Disposable disposable) {
    ApplicationManager.getApplication().getMessageBus().connect(disposable).subscribe(LafManagerListener.TOPIC, listener);
  }

  @Override
{'fraction_non_alphanumeric': 0.11303639958134667, 'fraction_numerical': 0.0034887777648563785, 'mean_word_length': 5.160100286532951, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6817521', 'n_tokens_mistral': 5541, 'n_tokens_neox': 5441, 'n_words': 964}