/** Invoked via reflection. */
  LafManagerImpl() {
    myListenerList = new EventListenerList();

    List<UIManager.LookAndFeelInfo> lafList = ContainerUtil.newArrayList();

    if (SystemInfo.isMac) {
      if (Registry.is("ide.mac.yosemite.laf")
          && isIntelliJLafEnabled()
          && SystemInfo.isJavaVersionAtLeast("1.8")) {
        lafList.add(new UIManager.LookAndFeelInfo("Default", IntelliJLaf.class.getName()));
      } else {
        lafList.add(
            new UIManager.LookAndFeelInfo("Default", UIManager.getSystemLookAndFeelClassName()));
      }
    } else {
      if (isIntelliJLafEnabled()) {
        lafList.add(new IntelliJLookAndFeelInfo());
      } else {
        lafList.add(new IdeaLookAndFeelInfo());
      }
      for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
        String name = laf.getName();
        if (!"Metal".equalsIgnoreCase(name)
            && !"CDE/Motif".equalsIgnoreCase(name)
            && !"Nimbus".equalsIgnoreCase(name)
            && !"Windows Classic".equalsIgnoreCase(name)
            && !name.startsWith("JGoodies")) {
          lafList.add(laf);
        }
      }
    }

    lafList.add(new DarculaLookAndFeelInfo());

    myLaFs = lafList.toArray(new UIManager.LookAndFeelInfo[lafList.size()]);

    if (!SystemInfo.isMac) {
      // do not sort LaFs on mac - the order is determined as Default, Darcula.
      // when we leave only system LaFs on other OSes, the order also should be determined as
      // Default, Darcula

      Arrays.sort(
          myLaFs,
          new Comparator<UIManager.LookAndFeelInfo>() {
            @Override
            public int compare(UIManager.LookAndFeelInfo obj1, UIManager.LookAndFeelInfo obj2) {
              String name1 = obj1.getName();
              String name2 = obj2.getName();
              return name1.compareToIgnoreCase(name2);
            }
          });
    }

    myCurrentLaf = getDefaultLaf();
  }
 /** Finds LAF by its class name. will be returned. */
 @Nullable
 private UIManager.LookAndFeelInfo findLaf(@Nullable String className) {
   if (className == null) {
     return null;
   }
   for (UIManager.LookAndFeelInfo laf : myLaFs) {
     if (Comparing.equal(laf.getClassName(), className)) {
       return laf;
     }
   }
   return null;
 }
  @Override
  public void initComponent() {
    if (myCurrentLaf != null) {
      final UIManager.LookAndFeelInfo laf = findLaf(myCurrentLaf.getClassName());
      if (laf != null) {
        setCurrentLookAndFeel(laf); // setup default LAF or one specified by readExternal.
      }
    }

    updateUI();

    if (SystemInfo.isXWindow) {
      myThemeChangeListener =
          new PropertyChangeListener() {
            @Override
            public void propertyChange(final PropertyChangeEvent evt) {
              //noinspection SSBasedInspection
              SwingUtilities.invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      fixGtkPopupStyle();
                      patchOptionPaneIcons(UIManager.getLookAndFeelDefaults());
                    }
                  });
            }
          };
      Toolkit.getDefaultToolkit()
          .addPropertyChangeListener(GNOME_THEME_PROPERTY_NAME, myThemeChangeListener);
    }
  }
  /** Sets current LAF. The method doesn't update component hierarchy. */
  @Override
  public void setCurrentLookAndFeel(UIManager.LookAndFeelInfo lookAndFeelInfo) {
    if (findLaf(lookAndFeelInfo.getClassName()) == null) {
      LOG.error("unknown LookAndFeel : " + lookAndFeelInfo);
      return;
    }
    // Set L&F
    if (IdeaLookAndFeelInfo.CLASS_NAME.equals(
        lookAndFeelInfo.getClassName())) { // that is IDEA default LAF
      IdeaLaf laf = new IdeaLaf();
      MetalLookAndFeel.setCurrentTheme(new IdeaBlueMetalTheme());
      try {
        UIManager.setLookAndFeel(laf);
      } catch (Exception e) {
        Messages.showMessageDialog(
            IdeBundle.message(
                "error.cannot.set.look.and.feel", lookAndFeelInfo.getName(), e.getMessage()),
            CommonBundle.getErrorTitle(),
            Messages.getErrorIcon());
        return;
      }
    } else if (DarculaLookAndFeelInfo.CLASS_NAME.equals(lookAndFeelInfo.getClassName())) {
      DarculaLaf laf = new DarculaLaf();
      try {
        UIManager.setLookAndFeel(laf);
        JBColor.setDark(true);
        IconLoader.setUseDarkIcons(true);
      } catch (Exception e) {
        Messages.showMessageDialog(
            IdeBundle.message(
                "error.cannot.set.look.and.feel", lookAndFeelInfo.getName(), e.getMessage()),
            CommonBundle.getErrorTitle(),
            Messages.getErrorIcon());
        return;
      }
    } else { // non default LAF
      try {
        LookAndFeel laf =
            ((LookAndFeel) Class.forName(lookAndFeelInfo.getClassName()).newInstance());
        if (laf instanceof MetalLookAndFeel) {
          MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
        }
        UIManager.setLookAndFeel(laf);
      } catch (Exception e) {
        Messages.showMessageDialog(
            IdeBundle.message(
                "error.cannot.set.look.and.feel", lookAndFeelInfo.getName(), e.getMessage()),
            CommonBundle.getErrorTitle(),
            Messages.getErrorIcon());
        return;
      }
    }
    myCurrentLaf =
        ObjectUtils.chooseNotNull(findLaf(lookAndFeelInfo.getClassName()), lookAndFeelInfo);

    checkLookAndFeel(lookAndFeelInfo, false);
  }
 @Override
 public Element getState() {
   Element element = new Element("state");
   if (myCurrentLaf != null) {
     String className = myCurrentLaf.getClassName();
     if (className != null) {
       Element child = new Element(ELEMENT_LAF);
       child.setAttribute(ATTRIBUTE_CLASS_NAME, className);
       element.addContent(child);
     }
   }
   return element;
 }
  @Override
  public void loadState(final Element element) {
    String className = null;
    Element lafElement = element.getChild(ELEMENT_LAF);
    if (lafElement != null) {
      className = lafElement.getAttributeValue(ATTRIBUTE_CLASS_NAME);
      if (className != null && ourLafClassesAliases.containsKey(className)) {
        className = ourLafClassesAliases.get(className);
      }
    }

    UIManager.LookAndFeelInfo laf = findLaf(className);
    // If LAF is undefined (wrong class name or something else) we have set default LAF anyway.
    if (laf == null) {
      laf = getDefaultLaf();
    }

    if (myCurrentLaf != null && !laf.getClassName().equals(myCurrentLaf.getClassName())) {
      setCurrentLookAndFeel(laf);
      updateUI();
    }

    myCurrentLaf = laf;
  }
  @Override
  public void loadState(final Element element) {
    String className = null;
    for (final Object o : element.getChildren()) {
      Element child = (Element) o;
      if (ELEMENT_LAF.equals(child.getName())) {
        className = child.getAttributeValue(ATTRIBUTE_CLASS_NAME);
        break;
      }
    }

    UIManager.LookAndFeelInfo laf = findLaf(className);
    // If LAF is undefined (wrong class name or something else) we have set default LAF anyway.
    if (laf == null) {
      laf = getDefaultLaf();
    }

    if (myCurrentLaf != null && !laf.getClassName().equals(myCurrentLaf.getClassName())) {
      setCurrentLookAndFeel(laf);
      updateUI();
    }

    myCurrentLaf = laf;
  }
  private boolean checkLookAndFeel(final UIManager.LookAndFeelInfo lafInfo, final boolean confirm) {
    String message = null;

    if (lafInfo.getName().contains("GTK")
        && SystemInfo.isXWindow
        && !SystemInfo.isJavaVersionAtLeast("1.6.0_12")) {
      message = IdeBundle.message("warning.problem.laf.1");
    }

    if (message != null) {
      if (confirm) {
        final String[] options = {
          IdeBundle.message("confirm.set.look.and.feel"), CommonBundle.getCancelButtonText()
        };
        final int result =
            Messages.showOkCancelDialog(
                message,
                CommonBundle.getWarningTitle(),
                options[0],
                options[1],
                Messages.getWarningIcon());
        if (result == Messages.OK) {
          myLastWarning = message;
          return true;
        }
        return false;
      }

      if (!message.equals(myLastWarning)) {
        Notifications.Bus.notify(
            new Notification(
                Notifications.SYSTEM_MESSAGES_GROUP_ID,
                "L&F Manager",
                message,
                NotificationType.WARNING,
                NotificationListener.URL_OPENING_LISTENER));
        myLastWarning = message;
      }
    }

    return true;
  }
  @Override
  public void initComponent() {
    if (myCurrentLaf != null) {
      final UIManager.LookAndFeelInfo laf = findLaf(myCurrentLaf.getClassName());
      if (laf != null) {
        boolean needUninstall = UIUtil.isUnderDarcula();
        setCurrentLookAndFeel(laf); // setup default LAF or one specified by readExternal.
        if (WelcomeWizardUtil.getWizardLAF() != null) {
          if (UIUtil.isUnderDarcula()) {
            DarculaInstaller.install();
          } else if (needUninstall) {
            DarculaInstaller.uninstall();
          }
        }
      }
    }

    updateUI();

    if (SystemInfo.isXWindow) {
      myThemeChangeListener =
          new PropertyChangeListener() {
            @Override
            public void propertyChange(final PropertyChangeEvent evt) {
              //noinspection SSBasedInspection
              SwingUtilities.invokeLater(
                  new Runnable() {
                    @Override
                    public void run() {
                      fixGtkPopupStyle();
                      patchGtkDefaults(UIManager.getLookAndFeelDefaults());
                    }
                  });
            }
          };
      Toolkit.getDefaultToolkit()
          .addPropertyChangeListener(GNOME_THEME_PROPERTY_NAME, myThemeChangeListener);
    }
  }