feat(gui): change fonts size with UI zoom, use FlatLaf fonts bundle

This commit is contained in:
Skylot
2025-12-20 20:14:30 +00:00
parent 8b48219dc3
commit 0c3e6e77cd
44 changed files with 410 additions and 231 deletions
+2
View File
@@ -38,6 +38,8 @@ dependencies {
implementation("com.formdev:flatlaf:3.7")
implementation("com.formdev:flatlaf-intellij-themes:3.7")
implementation("com.formdev:flatlaf-extras:3.7")
implementation("com.formdev:flatlaf-fonts-inter:4.1")
implementation("com.formdev:flatlaf-fonts-jetbrains-mono:2.304")
implementation("com.google.code.gson:gson:2.13.2")
implementation("org.apache.commons:commons-lang3:3.20.0")
+4 -3
View File
@@ -35,13 +35,14 @@ public class JadxGUI {
LogCollector.register();
printSystemInfo();
LafManager.init(settings);
NLS.setLocale(settings.getLangLocale());
ExceptionDialog.registerUncaughtExceptionHandler();
NLS.setLocale(settings.getLangLocale());
SwingUtilities.invokeLater(() -> {
LafManager.init(settings);
settings.getFontSettings().updateDefaultFont();
MainWindow mw = new MainWindow(settings);
mw.init();
registerOpenFileHandler(mw);
mw.init();
});
} catch (Exception e) {
LOG.error("Error: {}", e.getMessage(), e);
@@ -159,7 +159,7 @@ public class QuarkReportPanel extends ContentPanel {
@Override
public void loadSettings() {
Font settingsFont = getMainWindow().getSettings().getFont();
Font settingsFont = getMainWindow().getSettings().getCodeFont();
this.font = settingsFont.deriveFont(settingsFont.getSize2D() + 1.f);
this.boldFont = font.deriveFont(Font.BOLD);
header.setFont(font);
@@ -14,7 +14,7 @@ import static jadx.gui.utils.UiUtils.wrapHtml;
public class ScriptCompletionRenderer extends CompletionCellRenderer {
public ScriptCompletionRenderer(JadxSettings settings) {
setDisplayFont(settings.getFont());
setDisplayFont(settings.getCodeFont());
}
@Override
@@ -225,7 +225,7 @@ public class ScriptContentPanel extends AbstractCodeContentPanel {
private void applySettings() {
JadxSettings settings = getSettings();
codeScrollPane.setLineNumbersEnabled(settings.getLineNumbersMode() != LineNumbersMode.DISABLE);
codeScrollPane.getGutter().setLineNumberFont(settings.getFont());
codeScrollPane.getGutter().setLineNumberFont(settings.getCodeFont());
scriptArea.loadSettings();
}
@@ -1,48 +0,0 @@
package jadx.gui.settings;
import java.awt.Font;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.utils.Utils;
import jadx.gui.utils.FontUtils;
public class FontLoader {
private static final Logger LOG = LoggerFactory.getLogger(FontLoader.class);
private final Font defaultFont;
private Font font;
public FontLoader(Font defaultFont) {
this.defaultFont = defaultFont;
this.font = defaultFont;
}
public Font getFont() {
return font;
}
public void setFont(@Nullable Font font) {
this.font = Utils.getOrElse(font, defaultFont);
}
public void load(String fontStr) {
if (fontStr == null || fontStr.isEmpty()) {
font = defaultFont;
} else {
try {
font = FontUtils.loadByStr(fontStr);
} catch (Exception e) {
LOG.warn("Failed to load font: {}, reset to default", fontStr, e);
font = defaultFont;
}
}
}
public String getFontStr() {
return FontUtils.convertToStr(font);
}
}
@@ -13,7 +13,6 @@ import java.util.Set;
import javax.swing.JFrame;
import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -37,6 +36,7 @@ import jadx.gui.cache.code.CodeCacheMode;
import jadx.gui.cache.usage.UsageCacheMode;
import jadx.gui.settings.data.SaveOptionEnum;
import jadx.gui.settings.data.ShortcutsWrapper;
import jadx.gui.settings.font.FontSettings;
import jadx.gui.ui.MainWindow;
import jadx.gui.ui.tab.dnd.TabDndGhostType;
import jadx.gui.utils.LangLocale;
@@ -49,14 +49,11 @@ public class JadxSettings {
private static final Logger LOG = LoggerFactory.getLogger(JadxSettings.class);
private static final int RECENT_PROJECTS_COUNT = 30;
private static final Font DEFAULT_FONT = new RSyntaxTextArea().getFont();
private final JadxConfigAdapter<JadxSettingsData> configAdapter;
private final ShortcutsWrapper shortcutsWrapper = new ShortcutsWrapper();
private final FontSettings fontSettings = new FontSettings();
private final FontLoader fontLoader = new FontLoader(DEFAULT_FONT);
// TODO: use default monospaced font
private final FontLoader smaliFontLoader = new FontLoader(DEFAULT_FONT);
private JadxSettingsData settingsData;
public JadxSettings(JadxConfigAdapter<JadxSettingsData> configAdapter) {
@@ -84,8 +81,7 @@ public class JadxSettings {
fixOnLoad();
// update custom fields
shortcutsWrapper.updateShortcuts(settingsData.getShortcuts());
fontLoader.load(settingsData.getFontStr());
smaliFontLoader.load(settingsData.getSmaliFontStr());
fontSettings.bindData(settingsData);
}
private void upgradeSettings(int fromVersion) {
@@ -336,24 +332,44 @@ public class JadxSettings {
public void setUiZoom(float uiZoom) {
settingsData.setUiZoom(uiZoom);
fontSettings.applyUiZoom(uiZoom, isApplyUiZoomToFonts());
}
public Font getFont() {
return fontLoader.getFont();
public boolean isApplyUiZoomToFonts() {
return settingsData.isApplyUiZoomToFonts();
}
public void setFont(@Nullable Font font) {
fontLoader.setFont(font);
settingsData.setFontStr(fontLoader.getFontStr());
public void setApplyUiZoomToFonts(boolean applyUiZoomToFonts) {
settingsData.setApplyUiZoomToFonts(applyUiZoomToFonts);
fontSettings.applyUiZoom(getUiZoom(), applyUiZoomToFonts);
}
public FontSettings getFontSettings() {
return fontSettings;
}
public Font getUiFont() {
return fontSettings.getUiFontAdapter().getEffectiveFont();
}
public void setUiFont(Font font) {
fontSettings.getUiFontAdapter().setFont(font);
}
public Font getCodeFont() {
return fontSettings.getCodeFontAdapter().getEffectiveFont();
}
public void setCodeFont(Font font) {
fontSettings.getCodeFontAdapter().setFont(font);
}
public Font getSmaliFont() {
return smaliFontLoader.getFont();
return fontSettings.getSmaliFontAdapter().getEffectiveFont();
}
public void setSmaliFont(@Nullable Font font) {
smaliFontLoader.setFont(font);
settingsData.setSmaliFontStr(smaliFontLoader.getFontStr());
public void setSmaliFont(Font font) {
fontSettings.getSmaliFontAdapter().setFont(font);
}
public String getEditorTheme() {
@@ -11,6 +11,8 @@ import javax.swing.JFrame;
import org.jetbrains.annotations.Nullable;
import com.google.gson.annotations.SerializedName;
import jadx.cli.LogHelper;
import jadx.gui.cache.code.CodeCacheMode;
import jadx.gui.cache.usage.UsageCacheMode;
@@ -53,8 +55,13 @@ public class JadxSettingsData extends JadxGUIArgs {
private JadxUpdateChannel jadxUpdateChannel = JadxUpdateChannel.STABLE;
private float uiZoom = 1.0f;
private String fontStr = "";
private boolean applyUiZoomToFonts = true;
private String uiFontStr = "";
@SerializedName(value = "codeFontStr", alternate = "fontStr")
private String codeFontStr = "";
private String smaliFontStr = "";
private String editorTheme = "";
private String lafTheme = LafManager.INITIAL_THEME_NAME;
@@ -399,12 +406,20 @@ public class JadxSettingsData extends JadxGUIArgs {
this.smaliAreaShowBytecode = smaliAreaShowBytecode;
}
public String getFontStr() {
return fontStr;
public String getUiFontStr() {
return uiFontStr;
}
public void setFontStr(String fontStr) {
this.fontStr = fontStr;
public void setUiFontStr(String uiFontStr) {
this.uiFontStr = uiFontStr;
}
public String getCodeFontStr() {
return codeFontStr;
}
public void setCodeFontStr(String codeFontStr) {
this.codeFontStr = codeFontStr;
}
public String getSmaliFontStr() {
@@ -439,6 +454,14 @@ public class JadxSettingsData extends JadxGUIArgs {
this.uiZoom = uiZoom;
}
public boolean isApplyUiZoomToFonts() {
return applyUiZoomToFonts;
}
public void setApplyUiZoomToFonts(boolean applyUiZoomToFonts) {
this.applyUiZoomToFonts = applyUiZoomToFonts;
}
public UsageCacheMode getUsageCacheMode() {
return usageCacheMode;
}
@@ -0,0 +1,95 @@
package jadx.gui.settings.font;
import java.awt.Font;
import java.util.Objects;
import java.util.function.Consumer;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import jadx.core.utils.Utils;
import jadx.gui.utils.FontUtils;
import jadx.gui.utils.UiUtils;
/**
* Common handler for font updates and sync with settings data.
*/
public class FontAdapter {
private static final Logger LOG = LoggerFactory.getLogger(FontAdapter.class);
private Font defaultFont;
private Font font;
private Font effectiveFont;
private Consumer<String> fontSetter;
private float uiZoom;
public FontAdapter(Font defaultFont) {
Objects.requireNonNull(defaultFont);
this.defaultFont = defaultFont;
this.font = defaultFont;
}
/**
* Load current font from data, and save font setter to future sync
*/
public void bindData(String fontStr, Consumer<String> fontStrSetter) {
font = loadFromStr(fontStr);
fontSetter = fontStrSetter;
}
public void setDefaultFont(Font newDefaultFont) {
Objects.requireNonNull(newDefaultFont);
Font prevDefaultFont = defaultFont;
defaultFont = newDefaultFont;
if (font == prevDefaultFont) {
// font was set to default => update it also
setFont(newDefaultFont);
}
}
public Font getFont() {
return font;
}
public Font getEffectiveFont() {
return effectiveFont;
}
public void setFont(@Nullable Font newFont) {
font = Utils.getOrElse(newFont, defaultFont);
fontSetter.accept(getFontStr());
applyFontZoom();
}
public void setUiZoom(float uiZoom) {
this.uiZoom = uiZoom;
applyFontZoom();
}
private Font loadFromStr(String fontStr) {
if (fontStr != null && !fontStr.isEmpty()) {
try {
return FontUtils.loadByStr(fontStr);
} catch (Exception e) {
LOG.warn("Failed to load font: {}, reset to default", fontStr, e);
}
}
return defaultFont;
}
private String getFontStr() {
if (font == defaultFont) {
return "";
}
return FontUtils.convertToStr(font);
}
private void applyFontZoom() {
if (UiUtils.nearlyEqual(uiZoom, 1.0f)) {
effectiveFont = font;
} else {
effectiveFont = font.deriveFont(font.getSize2D() * uiZoom);
}
}
}
@@ -0,0 +1,82 @@
package jadx.gui.settings.font;
import java.awt.Font;
import javax.swing.UIManager;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.fonts.inter.FlatInterFont;
import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import jadx.gui.settings.JadxSettingsData;
import jadx.gui.utils.UiUtils;
/**
* Handle all font related settings
*/
public class FontSettings {
static {
FlatInterFont.install();
FlatJetBrainsMonoFont.install();
FlatLaf.setPreferredMonospacedFontFamily(FlatJetBrainsMonoFont.FAMILY);
}
private final FontAdapter uiFontAdapter;
private final FontAdapter codeFontAdapter;
private final FontAdapter smaliFontAdapter;
private float uiZoom;
private boolean applyUiZoomToFonts;
public FontSettings() {
int defFontSize = 13;
Font defUiFont = new Font(FlatInterFont.FAMILY, Font.PLAIN, defFontSize);
Font defCodeFont = new Font(FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, defFontSize);
uiFontAdapter = new FontAdapter(defUiFont);
codeFontAdapter = new FontAdapter(defCodeFont);
smaliFontAdapter = new FontAdapter(defCodeFont);
}
public void bindData(JadxSettingsData data) {
uiFontAdapter.bindData(data.getUiFontStr(), data::setUiFontStr);
codeFontAdapter.bindData(data.getCodeFontStr(), data::setCodeFontStr);
smaliFontAdapter.bindData(data.getSmaliFontStr(), data::setSmaliFontStr);
applyUiZoom(data.getUiZoom(), data.isApplyUiZoomToFonts());
}
/**
* Fetch and apply default font settings after FlatLaf init.
*/
public void updateDefaultFont() {
Font defaultFont = UIManager.getFont("defaultFont");
if (defaultFont != null) {
uiFontAdapter.setDefaultFont(defaultFont);
}
}
public synchronized void applyUiZoom(float newUiZoom, boolean newApplyUiZoomToFonts) {
if (UiUtils.nearlyEqual(uiZoom, newUiZoom) && applyUiZoomToFonts == newApplyUiZoomToFonts) {
return;
}
uiZoom = newUiZoom;
applyUiZoomToFonts = newApplyUiZoomToFonts;
float effectiveFontZoom = newApplyUiZoomToFonts ? newUiZoom : 1.0f;
uiFontAdapter.setUiZoom(effectiveFontZoom);
codeFontAdapter.setUiZoom(effectiveFontZoom);
smaliFontAdapter.setUiZoom(effectiveFontZoom);
}
public FontAdapter getUiFontAdapter() {
return uiFontAdapter;
}
public FontAdapter getCodeFontAdapter() {
return codeFontAdapter;
}
public FontAdapter getSmaliFontAdapter() {
return smaliFontAdapter;
}
}
@@ -4,6 +4,7 @@ import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
@@ -62,6 +63,8 @@ import jadx.gui.settings.JadxUpdateChannel;
import jadx.gui.settings.LineNumbersMode;
import jadx.gui.settings.XposedCodegenLanguage;
import jadx.gui.settings.data.SaveOptionEnum;
import jadx.gui.settings.font.FontAdapter;
import jadx.gui.settings.font.FontSettings;
import jadx.gui.settings.ui.cache.CacheSettingsGroup;
import jadx.gui.settings.ui.font.JadxFontDialog;
import jadx.gui.settings.ui.plugins.PluginSettings;
@@ -397,9 +400,6 @@ public class JadxSettingsWindow extends JDialog {
}
languageCbx.addActionListener(e -> settings.setLangLocale((LangLocale) languageCbx.getSelectedItem()));
JButton fontBtn = new JButton(NLS.str("preferences.select_font"));
JButton smaliFontBtn = new JButton(NLS.str("preferences.select_smali_font"));
EditorThemeManager editorThemeManager = mainWindow.getEditorThemeManager();
JComboBox<ThemeIdAndName> themesCbx = new JComboBox<>(editorThemeManager.getThemeIdNameArray());
themesCbx.setSelectedItem(editorThemeManager.getCurrentThemeIdName());
@@ -425,41 +425,25 @@ public class JadxSettingsWindow extends JDialog {
mainWindow.loadSettings();
});
JCheckBox applyUiZoomToFontsChB = new JCheckBox();
applyUiZoomToFontsChB.setSelected(settings.isApplyUiZoomToFonts());
applyUiZoomToFontsChB.addItemListener(e -> {
settings.setApplyUiZoomToFonts(e.getStateChange() == ItemEvent.SELECTED);
mainWindow.loadSettings();
});
SettingsGroup group = new SettingsGroup(NLS.str("preferences.appearance"));
group.addRow(NLS.str("preferences.language"), languageCbx);
group.addRow(NLS.str("preferences.ui_zoom"), uiZoomSpinner);
group.addRow(NLS.str("preferences.apply_ui_zoom_to_fonts"), applyUiZoomToFontsChB);
FontSettings fontSettings = settings.getFontSettings();
addFontEditor(group, NLS.str("preferences.ui_font"), fontSettings.getUiFontAdapter(), false);
addFontEditor(group, NLS.str("preferences.code_font"), fontSettings.getCodeFontAdapter(), false);
addFontEditor(group, NLS.str("preferences.smali_font"), fontSettings.getSmaliFontAdapter(), true);
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() {
@Override
public void mouseClicked(MouseEvent e) {
Font font = new JadxFontDialog(JadxSettingsWindow.this, NLS.str("preferences.font"))
.select(settings.getFont(), false);
if (font != null) {
LOG.debug("Selected Font: {}", font);
settings.setFont(font);
mainWindow.loadSettings();
fontLabel.setText(getFontLabelStr());
}
}
});
smaliFontBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Font font = new JadxFontDialog(JadxSettingsWindow.this, NLS.str("preferences.smali_font"))
.select(settings.getSmaliFont(), true);
if (font != null) {
LOG.debug("Selected Font: {} for smali", font);
settings.setSmaliFont(font);
mainWindow.loadSettings();
smaliFontLabel.setText(getSmaliFontLabelStr());
}
}
});
JComboBox<TabDndGhostType> tabDndGhostTypeCbx = new JComboBox<>(TabDndGhostType.values());
tabDndGhostTypeCbx.setSelectedItem(settings.getTabDndGhostType());
@@ -472,16 +456,32 @@ public class JadxSettingsWindow extends JDialog {
return group;
}
private String getFontLabelStr() {
Font font = settings.getFont();
String fontStyleName = FontUtils.convertFontStyleToString(font.getStyle());
return NLS.str("preferences.font") + ": " + font.getFontName() + ' ' + fontStyleName + ' ' + font.getSize();
private void addFontEditor(SettingsGroup group, String title, FontAdapter fontAdapter, boolean monospace) {
JLabel fontLabel = new JLabel(getFontLabelStr(fontAdapter.getFont()));
JButton fontBtn = new JButton(NLS.str("preferences.select_font"));
fontBtn.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
Font font = new JadxFontDialog(JadxSettingsWindow.this, settings, title)
.select(fontAdapter.getFont(), monospace);
if (font != null) {
fontLabel.setText(getFontLabelStr(font));
fontAdapter.setFont(font);
mainWindow.loadSettings();
}
}
});
JPanel fontPanel = new JPanel();
fontPanel.setLayout(new FlowLayout(FlowLayout.LEFT));
fontPanel.add(fontLabel);
fontPanel.add(fontBtn);
group.addRow(title, fontPanel);
}
private String getSmaliFontLabelStr() {
Font font = settings.getSmaliFont();
String fontStyleName = FontUtils.convertFontStyleToString(font.getStyle());
return NLS.str("preferences.smali_font") + ": " + font.getFontName() + ' ' + fontStyleName + ' ' + font.getSize();
private static String getFontLabelStr(Font font) {
return font.getFamily()
+ ' ' + FontUtils.convertFontStyleToString(font.getStyle())
+ ' ' + font.getSize();
}
private SettingsGroup makeDecompilationGroup() {
@@ -1,6 +1,7 @@
package jadx.gui.settings.ui.font;
import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Font;
@@ -14,7 +15,6 @@ import org.drjekyll.fontchooser.FontChooser;
import org.jetbrains.annotations.Nullable;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.ui.JadxSettingsWindow;
import jadx.gui.utils.NLS;
public class JadxFontDialog extends JDialog {
@@ -24,9 +24,9 @@ public class JadxFontDialog extends JDialog {
private final JadxSettings settings;
private boolean selected = false;
public JadxFontDialog(JadxSettingsWindow settingsWindow, String title) {
super(settingsWindow, title, true);
settings = settingsWindow.getMainWindow().getSettings();
public JadxFontDialog(Dialog parent, JadxSettings settings, String title) {
super(parent, title, true);
this.settings = settings;
initComponents();
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
if (!settings.loadWindowPos(this)) {
@@ -54,9 +54,11 @@ import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.plaf.FontUIResource;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
@@ -265,7 +267,6 @@ public class MainWindow extends JFrame {
JadxEventQueue.register();
resetCache();
FontUtils.registerBundledFonts();
initUI();
this.editorSyncManager = new EditorSyncManager(this, tabbedPane);
this.backgroundExecutor = new BackgroundExecutor(settings, progressPane);
@@ -286,14 +287,6 @@ public class MainWindow extends JFrame {
treeSplitPane.setDividerLocation(settings.getTreeWidth());
heapUsageBar.setVisible(settings.isShowHeapUsageBar());
setVisible(true);
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
closeWindow();
}
});
processCommandLineArgs();
}
@@ -502,15 +495,17 @@ public class MainWindow extends JFrame {
private void open(List<Path> paths, Runnable onFinish) {
saveAll();
closeAll();
if (paths.size() == 1 && openSingleFile(paths.get(0), onFinish)) {
return;
}
// start new project
project = new JadxProject(this);
project.setFilePaths(paths);
showUndisplayedCharsDialog = false;
loadFiles(onFinish);
UiUtils.bgRun(() -> {
closeAll();
if (paths.size() == 1 && openSingleFile(paths.get(0), onFinish)) {
return;
}
// start new project
project = new JadxProject(this);
project.setFilePaths(paths);
showUndisplayedCharsDialog = false;
loadFiles(onFinish);
});
}
private boolean openSingleFile(Path singleFile, Runnable onFinish) {
@@ -1518,6 +1513,14 @@ public class MainWindow extends JFrame {
FlatInspector.install("ctrl shift alt X");
FlatUIDefaultsInspector.install("ctrl shift alt Y");
}
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
closeWindow();
}
});
}
public void setLocationAndPosition() {
@@ -1564,17 +1567,23 @@ public class MainWindow extends JFrame {
}
private void updateUiSettings() {
LafManager.updateLaf(settings);
editorThemeManager.setTheme(settings.getEditorTheme());
if (UIScale.setZoomFactor(settings.getUiZoom())) {
FlatLaf.updateUI();
boolean needUpdateUI = false;
Font defaultUiFont = UIManager.getFont("defaultFont");
Font uiFont = settings.getUiFont();
if (!uiFont.equals(defaultUiFont)) {
UIManager.put("defaultFont", new FontUIResource(uiFont));
setFont(uiFont);
needUpdateUI = true;
}
if (LafManager.updateLaf(settings)) {
needUpdateUI = true;
}
editorThemeManager.setTheme(settings.getEditorTheme());
Font font = settings.getFont();
Font largerFont = font.deriveFont(font.getSize() + 2.f);
setFont(largerFont);
tree.setFont(largerFont);
if (UIScale.setZoomFactor(settings.getUiZoom())) {
needUpdateUI = true;
}
tree.setFont(settings.getCodeFont());
tree.setRowHeight(-1);
tabbedPane.loadSettings();
@@ -1585,6 +1594,9 @@ public class MainWindow extends JFrame {
quickTabsTree.loadSettings();
}
shortcutsController.loadSettings();
if (needUpdateUI) {
FlatLaf.updateUI();
}
}
@SuppressWarnings("finally")
@@ -1835,7 +1847,7 @@ public class MainWindow extends JFrame {
StringBuilder nonDisplayString = new StringBuilder();
List<ClassNode> classes = wrapper.getRootNode().getClasses(true);
Font font = getSettings().getFont();
Font font = getSettings().getCodeFont();
boolean hasNonDisplayable = false;
for (ClassNode cls : classes) {
@@ -396,10 +396,10 @@ public abstract class AbstractCodeArea extends RSyntaxTextArea {
public static void loadCommonSettings(MainWindow mainWindow, RSyntaxTextArea area) {
JadxSettings settings = mainWindow.getSettings();
mainWindow.getEditorThemeManager().apply(area);
area.setFont(settings.getFont());
area.setFont(settings.getCodeFont());
Gutter gutter = RSyntaxUtilities.getGutter(area);
if (gutter != null) {
gutter.setLineNumberFont(settings.getFont());
gutter.setLineNumberFont(settings.getCodeFont());
}
}
@@ -123,7 +123,7 @@ public class CodePanel extends JPanel {
}
private synchronized void initLineNumbers() {
codeScrollPane.getGutter().setLineNumberFont(getSettings().getFont());
codeScrollPane.getGutter().setLineNumberFont(getSettings().getCodeFont());
LineNumbersMode mode = getLineNumbersMode();
if (mode == LineNumbersMode.DISABLE) {
codeScrollPane.setLineNumbersEnabled(false);
@@ -4,7 +4,6 @@ import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.event.MouseAdapter;
@@ -121,8 +120,7 @@ public class ADBDialog extends JDialog implements ADB.DeviceStateListener, ADB.J
procTreeModel = new DefaultTreeModel(procTreeRoot);
procTree.setModel(procTreeModel);
procTree.setRowHeight(-1);
Font font = mainWindow.getSettings().getFont();
procTree.setFont(font.deriveFont(font.getSize() + 1.f));
procTree.setFont(mainWindow.getSettings().getCodeFont());
procTree.addMouseListener(new MouseAdapter() {
@Override
@@ -119,7 +119,7 @@ public class CommentDialog extends CommonDialog {
commentArea = new JTextArea();
TextStandardActions.attach(commentArea);
commentArea.setEditable(true);
commentArea.setFont(mainWindow.getSettings().getFont());
commentArea.setFont(mainWindow.getSettings().getCodeFont());
commentArea.setAlignmentX(Component.LEFT_ALIGNMENT);
commentArea.addKeyListener(new KeyAdapter() {
@@ -90,7 +90,7 @@ public abstract class CommonSearchDialog extends JFrame {
this.mainWindow = mainWindow;
this.tabsController = mainWindow.getTabsController();
this.cache = mainWindow.getCacheObject();
this.codeFont = mainWindow.getSettings().getFont();
this.codeFont = mainWindow.getSettings().getCodeFont();
this.windowTitle = title;
UiUtils.setWindowIcons(this);
updateTitle("");
@@ -283,10 +283,10 @@ public abstract class CommonSearchDialog extends JFrame {
JScrollPane scroll = new JScrollPane(resultsTable, VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
resultsInfoLabel = new JLabel("");
resultsInfoLabel.setFont(mainWindow.getSettings().getFont());
resultsInfoLabel.setFont(mainWindow.getSettings().getUiFont());
progressInfoLabel = new JLabel("");
progressInfoLabel.setFont(mainWindow.getSettings().getFont());
progressInfoLabel.setFont(mainWindow.getSettings().getUiFont());
progressInfoLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
@@ -195,7 +195,7 @@ public class ExcludePkgDialog extends JDialog {
}
private void initCheckbox() {
Font tmp = mainWindow.getSettings().getFont();
Font tmp = mainWindow.getSettings().getCodeFont();
Font font = tmp.deriveFont(tmp.getSize() + 1.f);
Set<String> excluded = new HashSet<>(mainWindow.getWrapper().getExcludedPackages());
walkTree(false, p -> p.initCheckbox(excluded.contains(p.getFullName()), font));
@@ -156,7 +156,7 @@ public class RenameDialog extends CommonDialog {
lbl.setLabelFor(nodeLabel);
renameField = new JTextField(40);
renameField.setFont(mainWindow.getSettings().getFont());
renameField.setFont(mainWindow.getSettings().getCodeFont());
renameField.getDocument().addDocumentListener(new DocumentUpdateListener(ev -> checkNewName(renameField.getText())));
renameField.addActionListener(e -> rename());
new TextStandardActions(renameField);
@@ -185,7 +185,7 @@ public class UsageDialog extends CommonSearchDialog {
private void initUI() {
JadxSettings settings = mainWindow.getSettings();
Font codeFont = settings.getFont();
Font codeFont = settings.getCodeFont();
JLabel lbl = new JLabel(NLS.str("usage_dialog.label"));
lbl.setFont(codeFont);
JLabel nodeLabel = NodeLabel.longName(node);
@@ -130,7 +130,7 @@ public class UsageDialogPlus extends CommonSearchDialog {
usageTree.putClientProperty("JTree.lineStyle", "Horizontal");
usageTree.setRowHeight(22);
usageTree.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
usageTree.setFont(mainWindow.getSettings().getFont());
usageTree.setFont(mainWindow.getSettings().getCodeFont());
// Use a custom renderer instead of a custom UI
usageTree.setCellRenderer(new PathHighlightTreeCellRenderer());
@@ -61,7 +61,7 @@ public class HexPreviewPanel extends JPanel {
public HexPreviewPanel(JadxSettings settings) {
hexCodeArea = new SectCodeArea();
hexCodeArea.setCodeFont(settings.getFont());
hexCodeArea.setCodeFont(settings.getSmaliFont());
hexCodeArea.setEditMode(EditMode.READ_ONLY);
hexCodeArea.setCharset(StandardCharsets.UTF_8);
hexCodeArea.setComponentPopupMenu(new JPopupMenu() {
@@ -80,7 +80,7 @@ public class HexPreviewPanel extends JPanel {
inspector = new HexInspectorPanel();
searchBar = new HexSearchBar(hexCodeArea);
header = new HexEditorHeader(hexCodeArea);
header.setFont(settings.getFont());
header.setFont(settings.getUiFont());
CodeAreaPainter painter = hexCodeArea.getPainter();
defaultColors = (SectionCodeAreaColorProfile) hexCodeArea.getColorsProfile();
@@ -34,7 +34,7 @@ public final class HtmlPanel extends ContentPanel {
@Override
public void loadSettings() {
JadxSettings settings = getMainWindow().getSettings();
textArea.setFont(settings.getFont());
textArea.setFont(settings.getUiFont());
}
public void loadContent(JNode jnode) {
@@ -420,7 +420,7 @@ public class JDebuggerPanel extends JPanel {
public void loadSettings() {
UiUtils.uiThreadGuard();
Font font = mainWindow.getSettings().getFont();
Font font = mainWindow.getSettings().getCodeFont();
variableTree.setFont(font.deriveFont(font.getSize() + 1.f));
variableTree.setRowHeight(-1);
stackFrameList.setFont(font);
@@ -478,7 +478,7 @@ public class JDebuggerPanel extends JPanel {
elements.forEach(model::addElement);
}
threadBox.updateUI();
stackFrameList.setFont(mainWindow.getSettings().getFont());
stackFrameList.setFont(mainWindow.getSettings().getCodeFont());
});
}
@@ -487,7 +487,7 @@ public class JDebuggerPanel extends JPanel {
DefaultListModel<IListElement> model =
(DefaultListModel<IListElement>) stackFrameList.getModel();
elements.forEach(model::addElement);
stackFrameList.setFont(mainWindow.getSettings().getFont());
stackFrameList.setFont(mainWindow.getSettings().getCodeFont());
}
SwingUtilities.invokeLater(stackFrameList::repaint);
}
@@ -48,7 +48,7 @@ public class SimpleCodePanel extends JPanel {
// The title label
titleLabel = new JLabel(NLS.str("usage_dialog_plus.code_view"));
titleLabel.setFont(settings.getFont());
titleLabel.setFont(settings.getCodeFont());
titleLabel.setBorder(BorderFactory.createEmptyBorder(5, 5, 10, 5));
// The code area
@@ -67,8 +67,8 @@ public class SimpleCodePanel extends JPanel {
private void applySettings(JadxSettings settings) {
codeScrollPane.setLineNumbersEnabled(settings.getLineNumbersMode() != LineNumbersMode.DISABLE);
codeScrollPane.getGutter().setLineNumberFont(settings.getFont());
codeArea.setFont(settings.getFont());
codeScrollPane.getGutter().setLineNumberFont(settings.getCodeFont());
codeArea.setFont(settings.getCodeFont());
}
public void showCode(JNode node, String codeLine) {
@@ -4,7 +4,6 @@ import java.awt.BorderLayout;
import java.awt.Font;
import javax.swing.BorderFactory;
import javax.swing.SwingUtilities;
import org.drjekyll.fontchooser.FontChooser;
import org.drjekyll.fontchooser.model.FontSelectionModel;
@@ -30,7 +29,7 @@ public class UndisplayedStringsPanel extends ContentPanel {
textPane = AbstractCodeArea.getDefaultArea(panel.getMainWindow());
JadxSettings settings = getSettings();
Font selectedFont = settings.getFont();
Font selectedFont = settings.getCodeFont();
FontChooser fontChooser = new FontChooser();
fontChooser.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
@@ -39,10 +38,8 @@ public class UndisplayedStringsPanel extends ContentPanel {
fontChooser.addChangeListener(event -> {
FontSelectionModel model = (FontSelectionModel) event.getSource();
settings.setFont(model.getSelectedFont());
SwingUtilities.invokeLater(() -> {
getMainWindow().loadSettings();
});
settings.setCodeFont(model.getSelectedFont());
getMainWindow().loadSettings();
});
codeScrollPane = new RTextScrollPane(textPane);
@@ -56,8 +53,8 @@ public class UndisplayedStringsPanel extends ContentPanel {
private void applySettings() {
codeScrollPane.setLineNumbersEnabled(getSettings().getLineNumbersMode() != LineNumbersMode.DISABLE);
codeScrollPane.getGutter().setLineNumberFont(getSettings().getFont());
textPane.setFont(getSettings().getFont());
codeScrollPane.getGutter().setLineNumberFont(getSettings().getCodeFont());
textPane.setFont(getSettings().getCodeFont());
}
private void showData(String data) {
@@ -47,7 +47,7 @@ public class StartPagePanel extends ContentPanel {
super(tabbedPane, node);
this.mainWindow = tabbedPane.getMainWindow();
this.settings = mainWindow.getSettings();
Font baseFont = settings.getFont();
Font baseFont = settings.getUiFont();
JButton openFile = new JButton(NLS.str("file.open_title"), Icons.OPEN);
openFile.addActionListener(ev -> mainWindow.openFileDialog());
@@ -1,7 +1,6 @@
package jadx.gui.ui.tab;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
@@ -161,10 +160,7 @@ public class QuickTabsTree extends JTree implements ITabStatesListener, TreeSele
}
public void loadSettings() {
Font font = mainWindow.getSettings().getFont();
Font largerFont = font.deriveFont(font.getSize() + 2.f);
setFont(largerFont);
setFont(mainWindow.getSettings().getCodeFont());
}
public void dispose() {
@@ -64,7 +64,7 @@ public class TabComponent extends JPanel {
}
private Font getLabelFont() {
Font font = tabsController.getMainWindow().getSettings().getFont();
Font font = tabsController.getMainWindow().getSettings().getCodeFont();
int style = font.getStyle();
style |= Font.BOLD;
if (getBlueprint().isPreviewTab()) {
@@ -1,7 +1,6 @@
package jadx.gui.utils;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.io.InputStream;
import javax.swing.text.StyleContext;
@@ -15,37 +14,31 @@ import jadx.core.utils.exceptions.JadxRuntimeException;
public class FontUtils {
private static final Logger LOG = LoggerFactory.getLogger(FontUtils.class);
public static final Font FONT_HACK = openFontTTF("Hack-Regular");
public static void registerBundledFonts() {
GraphicsEnvironment grEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
if (FontUtils.FONT_HACK != null) {
grEnv.registerFont(FontUtils.FONT_HACK);
}
}
public static Font loadByStr(String fontDesc) {
String[] parts = fontDesc.split("/");
if (parts.length != 3) {
throw new JadxRuntimeException("Unsupported font description format: " + fontDesc);
}
String name = parts[0];
String family = parts[0];
int style = parseFontStyle(parts[1]);
int size = Integer.parseInt(parts[2]);
StyleContext sc = StyleContext.getDefaultStyleContext();
Font font = sc.getFont(name, style, size);
Font font = sc.getFont(family, style, size);
if (font == null) {
throw new JadxRuntimeException("Font not found: " + fontDesc);
}
return font;
}
public static String convertToStr(Font font) {
public static String convertToStr(@Nullable Font font) {
if (font == null) {
return "";
}
if (font.getSize() < 1) {
throw new JadxRuntimeException("Bad font size: " + font.getSize());
}
return font.getFontName()
return font.getFamily()
+ '/' + convertFontStyleToString(font.getStyle())
+ '/' + font.getSize();
}
@@ -11,9 +11,7 @@ import org.slf4j.LoggerFactory;
import com.formdev.flatlaf.FlatDarculaLaf;
import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatIntelliJLaf;
import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.FlatLightLaf;
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes;
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
import com.formdev.flatlaf.themes.FlatMacLightLaf;
@@ -37,12 +35,8 @@ public class LafManager {
settings.sync();
}
public static void updateLaf(JadxSettings settings) {
if (setupLaf(getThemeClass(settings))) {
// update all components
FlatAnimatedLafChange.hideSnapshotWithAnimation();
FlatLaf.updateUI();
}
public static boolean updateLaf(JadxSettings settings) {
return setupLaf(getThemeClass(settings));
}
public static String[] getThemes() {
@@ -84,7 +78,6 @@ public class LafManager {
private static boolean applyLaf(String theme) {
try {
FlatAnimatedLafChange.showSnapshot();
UIManager.setLookAndFeel(theme);
return true;
} catch (Exception e) {
@@ -531,4 +531,8 @@ public class UiUtils {
}
field.repaint();
}
public static boolean nearlyEqual(float a, float b) {
return Math.abs(a - b) < 1E-6f;
}
}
@@ -10,6 +10,9 @@ import javax.swing.JComponent;
import javax.swing.KeyStroke;
import jadx.gui.settings.JadxSettings;
import jadx.gui.settings.font.FontAdapter;
import jadx.gui.settings.font.FontSettings;
import jadx.gui.ui.codearea.SmaliArea;
import jadx.gui.utils.UiUtils;
public class ZoomActions {
@@ -57,12 +60,15 @@ public class ZoomActions {
}
private void textZoom(int change) {
Font font = settings.getFont();
if (component.getFont().equals(font)) {
settings.setFont(changeFontSize(font, change));
FontSettings fontSettings = settings.getFontSettings();
FontAdapter fontAdapter;
if (component instanceof SmaliArea) {
fontAdapter = fontSettings.getSmaliFontAdapter();
} else {
settings.setSmaliFont(changeFontSize(settings.getSmaliFont(), change));
fontAdapter = fontSettings.getCodeFontAdapter();
}
fontAdapter.setFont(changeFontSize(fontAdapter.getFont(), change));
settings.sync();
update.run();
}
Binary file not shown.
@@ -271,14 +271,15 @@ preferences.update_channel=Jadx-Updatekanal
preferences.integerFormat=Ganzzahlformat
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=Schriftart ändern
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=Schriftart ändern
preferences.smali_font=Monospaced-Schriftart (Smali/Hex)
preferences.laf_theme=Thema
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Thema ändern
preferences.start_jobs=Autom. Hintergrunddekompilierung starten
preferences.select_font=Ändern
preferences.select_smali_font=Ändern
preferences.deobfuscation_on=Deobfuskierung einschalten
preferences.generated_renames_mapping_file_mode=Umgang mit Map-Dateien
preferences.deobfuscation_min_len=Minimale Namenlänge
@@ -271,14 +271,15 @@ preferences.disable_tooltip_on_hover=Disable tooltip on hover
preferences.integerFormat=Integer format
preferences.typeUpdatesCountLimit=Update type limit count
preferences.ui_zoom=UI Zoom factor
preferences.font=Editor font
preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
preferences.ui_font=UI font
preferences.code_font=Editor font
preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=Theme
preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Editor theme
preferences.start_jobs=Auto start background decompilation
preferences.select_font=Change
preferences.select_smali_font=Change
preferences.deobfuscation_on=Enable deobfuscation
preferences.generated_renames_mapping_file_mode=Map file handle mode
preferences.deobfuscation_min_len=Minimum name length
@@ -271,14 +271,15 @@ preferences.raw_cfg=Generate RAW CFG graphs
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=Fuente del editor
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=Fuente del editor
#preferences.smali_font=Monospaced font (Smali/Hex)
#preferences.laf_theme=Theme
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Tema del editor
preferences.start_jobs=Inicio autom. descompilación de fondo
preferences.select_font=Seleccionar
#preferences.select_smali_font=Change
preferences.deobfuscation_on=Activar desobfuscación
#preferences.generated_renames_mapping_file_mode=Map file handle mode
preferences.deobfuscation_min_len=Longitud mínima del nombre
@@ -271,14 +271,15 @@ preferences.raw_cfg=Hasilkan grafik CFG mentah
preferences.integerFormat=Format bilangan bulat
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=Font editor
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=Font editor
preferences.smali_font=Font monospasi (Smali/Hex)
preferences.laf_theme=Tema
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Tema editor
preferences.start_jobs=Deskompilasi latar belakang otomatis
preferences.select_font=Ubah
preferences.select_smali_font=Ubah
preferences.deobfuscation_on=Aktifkan deobfikasi
preferences.generated_renames_mapping_file_mode=Mode penanganan file pemetaan
preferences.deobfuscation_min_len=Panjang nama minimum
@@ -271,14 +271,15 @@ preferences.raw_cfg=RAW CFG 그래프 생성
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=에디터 글씨체
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=에디터 글씨체
#preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=테마
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=에디터 테마
preferences.start_jobs=백그라운드에서 디컴파일 자동 시작
preferences.select_font=변경
preferences.select_smali_font=변경
preferences.deobfuscation_on=난독 해제 활성화
preferences.generated_renames_mapping_file_mode=맵 파일 처리 모드
preferences.deobfuscation_min_len=최소 이름 길이
@@ -271,14 +271,15 @@ preferences.raw_cfg=Gera gráficos CFG no formato RAW
#preferences.integerFormat=Integer format
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=Fonte do editor
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=Fonte do editor
#preferences.smali_font=Monospaced font (Smali/Hex)
preferences.laf_theme=Tema
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Tema do editor
preferences.start_jobs=Inicializar descompilação automaticamente em segundo-plano
preferences.select_font=Alterar
preferences.select_smali_font=Alterar
preferences.deobfuscation_on=Ativar desofuscação
#preferences.generated_renames_mapping_file_mode=Map file handle mode
preferences.deobfuscation_min_len=Tamanho mínimo do nome
@@ -271,14 +271,15 @@ preferences.update_channel=Канал обновления Jadx
preferences.integerFormat=Формат чисел
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=Шрифт редактора Java
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=Шрифт редактора Java
preferences.smali_font=Шрифт smali/HEX редактора
preferences.laf_theme=Тема приложения
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=Тема редактора
preferences.start_jobs=Автоматическая декомпиляция
preferences.select_font=Изменить
preferences.select_smali_font=Изменить
preferences.deobfuscation_on=Включить деобфускацию
preferences.generated_renames_mapping_file_mode=Режим обработки маппингов
preferences.deobfuscation_min_len=Минимальная длина имени
@@ -271,14 +271,15 @@ preferences.disable_tooltip_on_hover=禁用悬停提示
preferences.integerFormat=数值格式化
preferences.typeUpdatesCountLimit=更新类型限制数量
#preferences.ui_zoom=UI Zoom factor
preferences.font=编辑器字体
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=编辑器字体
preferences.smali_font=等宽字体(Smali/Hex
preferences.laf_theme=主题
preferences.dynamic_editor_theme=使用 UI 主题色彩
preferences.theme=编辑器主题
preferences.start_jobs=自动进行后台反编译
preferences.select_font=修改
preferences.select_smali_font=修改
preferences.deobfuscation_on=启用反混淆
preferences.generated_renames_mapping_file_mode=映射文件句柄模式
preferences.deobfuscation_min_len=最小命名长度
@@ -271,14 +271,15 @@ preferences.update_channel=Jadx 更新頻道
preferences.integerFormat=整數模式
#preferences.typeUpdatesCountLimit=Update type limit count
#preferences.ui_zoom=UI Zoom factor
preferences.font=編輯器字型
#preferences.apply_ui_zoom_to_fonts=Apply UI zoom to fonts
#preferences.ui_font=UI font
preferences.code_font=編輯器字型
preferences.smali_font=等寬字型 (Smali/Hex)
preferences.laf_theme=主題
#preferences.dynamic_editor_theme=Use UI theme colors
preferences.theme=編輯器主題
preferences.start_jobs=自動開始背景反編譯
preferences.select_font=變更
preferences.select_smali_font=變更
preferences.deobfuscation_on=啟用去模糊化
preferences.generated_renames_mapping_file_mode=Map 檔案處理模式
preferences.deobfuscation_min_len=最小名稱長度