Skip to content

Commit

Permalink
feat(gui): use FlatLaf for themes support
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Aug 2, 2021
1 parent b63e3ac commit dd29d37
Show file tree
Hide file tree
Showing 12 changed files with 187 additions and 33 deletions.
6 changes: 5 additions & 1 deletion jadx-cli/src/main/java/jadx/cli/LogHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,14 @@ public static LogLevelEnum getLogLevel() {
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=
*/
Expand Down
4 changes: 4 additions & 0 deletions jadx-gui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
23 changes: 4 additions & 19 deletions jadx-gui/src/main/java/jadx/gui/JadxGUI.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package jadx.gui;

import javax.swing.SwingUtilities;
import javax.swing.UIManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -10,6 +9,7 @@
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;
Expand All @@ -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) {
Expand All @@ -39,19 +37,6 @@ public static void main(String[] args) {
}
}

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: {} {}",
Expand Down
10 changes: 10 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
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;

Expand Down Expand Up @@ -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 = "";
Expand Down Expand Up @@ -431,6 +433,14 @@ public void setEditorThemePath(String editorThemePath) {
this.editorThemePath = editorThemePath;
}

public String getLafTheme() {
return lafTheme;
}

public void setLafTheme(String lafTheme) {
this.lafTheme = lafTheme;
}

public int getMainWindowExtendedState() {
return mainWindowExtendedState;
}
Expand Down
60 changes: 52 additions & 8 deletions jadx-gui/src/main/java/jadx/gui/settings/JadxSettingsWindow.java
Original file line number Diff line number Diff line change
@@ -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 javax.swing.*;
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.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;
Expand All @@ -27,6 +62,7 @@
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;
Expand Down Expand Up @@ -75,7 +111,7 @@ private void initUI() {
leftPanel.add(makeDeobfuscationGroup());
leftPanel.add(makeRenameGroup());
leftPanel.add(makeProjectGroup());
leftPanel.add(makeEditorGroup());
leftPanel.add(makeAppearanceGroup());
leftPanel.add(makeOtherGroup());
leftPanel.add(makeSearchResGroup());

Expand Down Expand Up @@ -289,7 +325,7 @@ private SettingsGroup makeProjectGroup() {
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"));

Expand All @@ -308,9 +344,17 @@ private SettingsGroup makeEditorGroup() {
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() {
Expand Down
3 changes: 3 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
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;
Expand Down Expand Up @@ -1255,6 +1256,8 @@ public Theme getEditorTheme() {
}

public void loadSettings() {
LafManager.updateLaf(settings);

Font font = settings.getFont();
Font largerFont = font.deriveFont(font.getSize() + 2.f);

Expand Down
99 changes: 99 additions & 0 deletions jadx-gui/src/main/java/jadx/gui/utils/LafManager.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
3 changes: 2 additions & 1 deletion jadx-gui/src/main/resources/i18n/Messages_de_DE.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion jadx-gui/src/main/resources/i18n/Messages_en_US.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 2 additions & 1 deletion jadx-gui/src/main/resources/i18n/Messages_es_ES.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit dd29d37

Please sign in to comment.