package com.revivius.nb.darcula;
import com.bulenkov.darcula.DarculaLaf;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import javax.swing.UIManager;
import org.openide.modules.ModuleInstall;
import org.openide.util.Lookup;
import org.openide.util.NbPreferences;
import org.openide.windows.WindowManager;
/**
* Makes Darcula LAF available in preferred LAF combo, installs
* DarculaLFCustoms, set Preferences and switch the editor color profile to
* Darcula theme.
*
* @author Revivius
*/
public class Installer extends ModuleInstall {
private static final String COLOR_MODEL_CLASS_NAME = "org.netbeans.modules.options.colors.ColorModel";
private static boolean SWITCH_EDITOR_COLORS = false;
@Override
public void validate() throws IllegalStateException {
Preferences prefs = NbPreferences.root().node("laf");
if (!prefs.getBoolean("darcula.installed", false)) {
prefs.put("laf", DarculaLaf.class.getName());
SWITCH_EDITOR_COLORS = true;
}
prefs.putBoolean("darcula.installed", true);
// to make LAF available in Tools > Options > Appearance > Look and Feel
UIManager.installLookAndFeel(new UIManager.LookAndFeelInfo(DarculaLaf.NAME, DarculaLaf.class.getName()));
UIManager.put("Nb.DarculaLFCustoms", new DarculaLFCustoms());
}
@Override
public void restored() {
if (SWITCH_EDITOR_COLORS) {
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override
public void run() {
switchEditorColorsProfile();
}
});
};
}
/**
* Returns if possible to change color profile. Use reflection to
* instantiate ColorModel (private package) class and get the current
* profile.
*
* @return {@code true} if current profile not equals this theme profile
* name or {@code false} otherwise.
*/
private boolean isChangeEditorColorsPossible() {
ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class);
if (loader == null) {
loader = Installer.class.getClassLoader();
}
try {
Class claszz = loader.loadClass(COLOR_MODEL_CLASS_NAME);
Object colorModel = claszz.newInstance();
Method method = claszz.getDeclaredMethod("getCurrentProfile", new Class[0]);
Object invokeResult = method.invoke(colorModel, new Object[0]);
return invokeResult != null && !DarculaLaf.NAME.equals(invokeResult);
} catch (Exception ex) {
//ignore
Logger.getLogger(Installer.class.getName()).log(Level.INFO, "Cannot get the current editor colors profile.", ex);
}
return false;
}
/**
* Switch the editor color profile if possible. Use reflection to
* instantiate ColorModel (private package) class and set the current
* profile
*/
private void switchEditorColorsProfile() {
if (!isChangeEditorColorsPossible()) {
return;
}
ClassLoader loader = Lookup.getDefault().lookup(ClassLoader.class);
if (loader == null) {
loader = Installer.class.getClassLoader();
}
try {
Class classz = loader.loadClass(COLOR_MODEL_CLASS_NAME);
Object colorModel = classz.newInstance();
Method method = classz.getDeclaredMethod("setCurrentProfile", String.class);
method.invoke(colorModel, DarculaLaf.NAME);
// method call above changes the token colors but not annotation
// colors. these two seems to solve the problem
method = classz.getDeclaredMethod("getAnnotations", String.class);
Object acs = method.invoke(colorModel, DarculaLaf.NAME);
method = classz.getDeclaredMethod("setAnnotations", String.class, Collection.class);
method.invoke(colorModel, DarculaLaf.NAME, acs);
} catch (Exception ex) {
//ignore
Logger.getLogger(Installer.class.getName()).log(Level.INFO, "Cannot change editors colors profile.", ex);
}
}
}