feat(gui): use FlatLaf for themes support

This commit is contained in:
Skylot
2021-08-02 16:20:02 +01:00
parent b63e3aca00
commit dd29d37154
12 changed files with 186 additions and 32 deletions
@@ -66,10 +66,14 @@ public class LogHelper {
return logLevelValue;
}
private static void setLevelForClass(Class<?> cls, Level level) {
public static void setLevelForClass(Class<?> cls, Level level) {
((Logger) LoggerFactory.getLogger(cls)).setLevel(level);
}
public static void setLevelForPackage(String pkgName, Level level) {
((Logger) LoggerFactory.getLogger(pkgName)).setLevel(level);
}
/**
* Try to detect if user provide custom logback config via -Dlogback.configurationFile=
*/
+4
View File
@@ -15,6 +15,10 @@ dependencies {
implementation files('libs/jfontchooser-1.0.5.jar')
implementation 'hu.kazocsaba:image-viewer:1.2.3'
implementation 'com.formdev:flatlaf:1.4'
implementation 'com.formdev:flatlaf-intellij-themes:1.4'
implementation 'org.reflections:reflections:0.9.12'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'org.apache.commons:commons-text:1.9'
+4 -19
View File
@@ -1,7 +1,6 @@
package jadx.gui;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -10,6 +9,7 @@ import jadx.cli.LogHelper;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.JadxSettingsAdapter;
import jadx.gui.ui.MainWindow;
import jadx.gui.utils.LafManager;
import jadx.gui.utils.NLS;
import jadx.gui.utils.SystemInfo;
import jadx.gui.utils.logs.LogCollector;
@@ -20,17 +20,15 @@ public class JadxGUI {
public static void main(String[] args) {
try {
LogCollector.register();
final JadxSettings settings = JadxSettingsAdapter.load();
JadxSettings settings = JadxSettingsAdapter.load();
settings.setLogLevel(LogHelper.LogLevelEnum.INFO);
// overwrite loaded settings by command line arguments
if (!settings.overrideProvided(args)) {
return;
}
if (!tryDefaultLookAndFeel()) {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
NLS.setLocale(settings.getLangLocale());
printSystemInfo();
LafManager.init(settings);
NLS.setLocale(settings.getLangLocale());
SwingUtilities.invokeLater(new MainWindow(settings)::init);
} catch (Exception e) {
@@ -39,19 +37,6 @@ public class JadxGUI {
}
}
private static boolean tryDefaultLookAndFeel() {
String defLaf = System.getProperty("swing.defaultlaf");
if (defLaf != null) {
try {
UIManager.setLookAndFeel(defLaf);
return true;
} catch (Exception e) {
LOG.error("Failed to set default laf: {}", defLaf, e);
}
}
return false;
}
private static void printSystemInfo() {
if (LOG.isDebugEnabled()) {
LOG.debug("Starting jadx-gui. Version: '{}'. JVM: {} {}. OS: {} {}",
@@ -33,6 +33,7 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.codearea.EditorTheme;
import jadx.gui.utils.FontUtils;
import jadx.gui.utils.LafManager;
import jadx.gui.utils.LangLocale;
import jadx.gui.utils.NLS;
@@ -60,6 +61,7 @@ public class JadxSettings extends JadxCLIArgs {
private String fontStr = "";
private String smaliFontStr = "";
private String editorThemePath = "";
private String lafTheme = LafManager.SYSTEM_THEME_NAME;
private LangLocale langLocale = NLS.defaultLocale();
private boolean autoStartJobs = false;
protected String excludedPackages = "";
@@ -431,6 +433,14 @@ public class JadxSettings extends JadxCLIArgs {
this.editorThemePath = editorThemePath;
}
public String getLafTheme() {
return lafTheme;
}
public void setLafTheme(String lafTheme) {
this.lafTheme = lafTheme;
}
public int getMainWindowExtendedState() {
return mainWindowExtendedState;
}
@@ -1,15 +1,50 @@
package jadx.gui.settings;
import java.awt.*;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
import java.awt.event.ItemEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import javax.swing.*;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
@@ -27,6 +62,7 @@ import jadx.api.JadxArgs;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.codearea.EditorTheme;
import jadx.gui.utils.FontUtils;
import jadx.gui.utils.LafManager;
import jadx.gui.utils.LangLocale;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
@@ -75,7 +111,7 @@ public class JadxSettingsWindow extends JDialog {
leftPanel.add(makeDeobfuscationGroup());
leftPanel.add(makeRenameGroup());
leftPanel.add(makeProjectGroup());
leftPanel.add(makeEditorGroup());
leftPanel.add(makeAppearanceGroup());
leftPanel.add(makeOtherGroup());
leftPanel.add(makeSearchResGroup());
@@ -289,7 +325,7 @@ public class JadxSettingsWindow extends JDialog {
return group;
}
private SettingsGroup makeEditorGroup() {
private SettingsGroup makeAppearanceGroup() {
JButton fontBtn = new JButton(NLS.str("preferences.select_font"));
JButton smaliFontBtn = new JButton(NLS.str("preferences.select_smali_font"));
@@ -308,9 +344,17 @@ public class JadxSettingsWindow extends JDialog {
mainWindow.loadSettings();
});
SettingsGroup group = new SettingsGroup(NLS.str("preferences.editor"));
JLabel fontLabel = group.addRow(getFontLabelStr(), fontBtn);
JComboBox<String> lafCbx = new JComboBox<>(LafManager.getThemes());
lafCbx.setSelectedItem(settings.getLafTheme());
lafCbx.addActionListener(e -> {
settings.setLafTheme((String) lafCbx.getSelectedItem());
mainWindow.loadSettings();
});
SettingsGroup group = new SettingsGroup(NLS.str("preferences.appearance"));
group.addRow(NLS.str("preferences.laf_theme"), lafCbx);
group.addRow(NLS.str("preferences.theme"), themesCbx);
JLabel fontLabel = group.addRow(getFontLabelStr(), fontBtn);
JLabel smaliFontLabel = group.addRow(getSmaliFontLabelStr(), smaliFontBtn);
fontBtn.addMouseListener(new MouseAdapter() {
@@ -115,6 +115,7 @@ import jadx.gui.utils.CacheObject;
import jadx.gui.utils.CodeUsageInfo;
import jadx.gui.utils.FontUtils;
import jadx.gui.utils.JumpPosition;
import jadx.gui.utils.LafManager;
import jadx.gui.utils.Link;
import jadx.gui.utils.NLS;
import jadx.gui.utils.SystemInfo;
@@ -1255,6 +1256,8 @@ public class MainWindow extends JFrame {
}
public void loadSettings() {
LafManager.updateLaf(settings);
Font font = settings.getFont();
Font largerFont = font.deriveFont(font.getSize() + 2.f);
@@ -0,0 +1,99 @@
package jadx.gui.utils;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.LookAndFeel;
import javax.swing.UIManager;
import org.reflections.Reflections;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.formdev.flatlaf.FlatLaf;
import ch.qos.logback.classic.Level;
import jadx.cli.LogHelper;
import jadx.gui.settings.JadxSettings;
public class LafManager {
private static final Logger LOG = LoggerFactory.getLogger(LafManager.class);
public static final String SYSTEM_THEME_NAME = "default";
private static final Map<String, String> THEMES_MAP = initThemesMap();
public static void init(JadxSettings settings) {
if (setupLaf(getThemeClass(settings))) {
return;
}
setupLaf(SYSTEM_THEME_NAME);
settings.setLafTheme(SYSTEM_THEME_NAME);
settings.sync();
}
public static void updateLaf(JadxSettings settings) {
if (setupLaf(getThemeClass(settings))) {
FlatLaf.updateUI();
}
}
public static String[] getThemes() {
return THEMES_MAP.keySet().toArray(new String[0]);
}
private static String getThemeClass(JadxSettings settings) {
return THEMES_MAP.get(settings.getLafTheme());
}
private static boolean setupLaf(String themeClass) {
if (SYSTEM_THEME_NAME.equals(themeClass)) {
return applyLaf(UIManager.getSystemLookAndFeelClassName());
}
if (themeClass != null && !themeClass.isEmpty()) {
return applyLaf(themeClass);
}
return false;
}
private static Map<String, String> initThemesMap() {
Map<String, String> map = new LinkedHashMap<>();
map.put(SYSTEM_THEME_NAME, SYSTEM_THEME_NAME);
for (FlatLaf flatLafTheme : collectFlatLafThemes()) {
map.put(flatLafTheme.getName(), flatLafTheme.getClass().getName());
}
return map;
}
private static List<FlatLaf> collectFlatLafThemes() {
LogHelper.setLevelForPackage("org.reflections", Level.WARN);
Reflections reflections = new Reflections("com.formdev.flatlaf");
Set<Class<? extends FlatLaf>> lafClasses = reflections.getSubTypesOf(FlatLaf.class);
List<FlatLaf> themes = new ArrayList<>(lafClasses.size());
for (Class<? extends FlatLaf> lafClass : lafClasses) {
try {
themes.add(lafClass.getDeclaredConstructor().newInstance());
} catch (Exception e) {
// some classes not themes, ignore them
LOG.trace("Failed make instance for class: {}", lafClass.getName(), e);
}
}
themes.sort(Comparator.comparing(LookAndFeel::getName));
return themes;
}
private static boolean applyLaf(String theme) {
try {
UIManager.setLookAndFeel(theme);
return true;
} catch (Exception e) {
LOG.error("Failed to set laf to {}", theme, e);
return false;
}
}
}
@@ -113,7 +113,7 @@ about_dialog.title=Über JADX
preferences.title=Einstellungen
preferences.deobfuscation=Deobfuscation
preferences.editor=Editor
#preferences.appearance=Appearance
preferences.decompile=Dekompilierung
preferences.project=Projekt
preferences.other=Andere
@@ -139,6 +139,7 @@ preferences.cfg=Methoden generieren CFG-Grafiken (im 'Punkt'-Format)
preferences.raw_cfg=RAW CFG-Grafiken generieren
preferences.font=Schrift ändern
#preferences.smali_font=
#preferences.laf_theme=Theme
preferences.theme=Thema ändern
preferences.start_jobs=Autom. Hintergrunddekompilierung starten
preferences.select_font=Ändern
@@ -113,7 +113,7 @@ about_dialog.title=About JADX
preferences.title=Preferences
preferences.deobfuscation=Deobfuscation
preferences.editor=Editor
preferences.appearance=Appearance
preferences.decompile=Decompilation
preferences.project=Project
preferences.other=Other
@@ -139,6 +139,7 @@ preferences.cfg=Generate methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
preferences.font=Editor font
preferences.smali_font=Smali Editor font
preferences.laf_theme=Theme
preferences.theme=Editor theme
preferences.start_jobs=Auto start background decompilation
preferences.select_font=Change
@@ -113,7 +113,7 @@ about_dialog.title=Sobre JADX
preferences.title=Preferencias
preferences.deobfuscation=Desofuscación
preferences.editor=Editor
#preferences.appearance=Appearance
preferences.decompile=Descompilación
#preferences.project=
preferences.other=Otros
@@ -139,6 +139,7 @@ preferences.cfg=Generar methods CFG graphs (in 'dot' format)
preferences.raw_cfg=Generate RAW CFG graphs
preferences.font=Fuente del editor
#preferences.smali_font=
#preferences.laf_theme=Theme
preferences.theme=Tema del editor
preferences.start_jobs=Inicio autom. descompilación de fondo
preferences.select_font=Seleccionar
@@ -113,7 +113,7 @@ about_dialog.title=JADX 정보
preferences.title=설정
preferences.deobfuscation=난독화 해제
preferences.editor=에디터
#preferences.appearance=Appearance
preferences.decompile=디컴파일
preferences.project=프로젝트
preferences.other=기타
@@ -139,6 +139,7 @@ preferences.cfg=메소드 CFG 그래프 생성 ('dot' 포맷)
preferences.raw_cfg=RAW CFG 그래프 생성
preferences.font=에디터 글씨체
preferences.smali_font=Smali 에디터 글씨체
#preferences.laf_theme=Theme
preferences.theme=에디터 테마
preferences.start_jobs=백그라운드에서 디컴파일 자동 시작
preferences.select_font=변경
@@ -113,7 +113,7 @@ about_dialog.title=关于 JADX
preferences.title=首选项
preferences.deobfuscation=反混淆
preferences.editor=编辑器
#preferences.appearance=Appearance
preferences.decompile=反编译
preferences.project=项目
preferences.other=其他
@@ -139,6 +139,7 @@ preferences.cfg=生成方法的 CFG 图(以 .dot 格式保存)
preferences.raw_cfg=生成原始的 CFG 图
preferences.font=编辑器字体
#preferences.smali_font=
#preferences.laf_theme=Theme
preferences.theme=编辑器主题
preferences.start_jobs=自动进行后台反编译
preferences.select_font=更改