diff --git a/jadx-gui/build.gradle.kts b/jadx-gui/build.gradle.kts index eaeaa05df..5931e54b0 100644 --- a/jadx-gui/build.gradle.kts +++ b/jadx-gui/build.gradle.kts @@ -31,7 +31,7 @@ dependencies { implementation("io.github.oshai:kotlin-logging-jvm:7.0.0") implementation("com.fifesoft:rsyntaxtextarea:3.4.1") - implementation(files("libs/jfontchooser-1.0.5.jar")) + implementation("org.drjekyll:fontchooser:3.1.0") implementation("hu.kazocsaba:image-viewer:1.2.3") implementation("com.formdev:flatlaf:3.5.1") diff --git a/jadx-gui/libs/jfontchooser-1.0.5.jar b/jadx-gui/libs/jfontchooser-1.0.5.jar deleted file mode 100644 index 3a9779f59..000000000 Binary files a/jadx-gui/libs/jfontchooser-1.0.5.jar and /dev/null differ diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/JPreferredFontChooser.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/JPreferredFontChooser.java deleted file mode 100644 index 785b4465b..000000000 --- a/jadx-gui/src/main/java/jadx/gui/settings/ui/JPreferredFontChooser.java +++ /dev/null @@ -1,52 +0,0 @@ -package jadx.gui.settings.ui; - -import java.awt.GraphicsEnvironment; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import say.swing.JFontChooser; - -public class JPreferredFontChooser extends JFontChooser { - private static final Logger LOG = LoggerFactory.getLogger(JPreferredFontChooser.class); - - private static final String[] PREFERRED_FONTS = new String[] { - "Monospaced", "Consolas", "Courier", "Courier New", - "Lucida Sans Typewriter", "Lucida Console", - "SimSun", "SimHei", - }; - - private String[] filteredFonts; - - @Override - protected String[] getFontFamilies() { - if (filteredFonts == null) { - GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); - Set fontSet = new HashSet<>(); - Collections.addAll(fontSet, env.getAvailableFontFamilyNames()); - List found = new ArrayList<>(PREFERRED_FONTS.length); - for (String font : PREFERRED_FONTS) { - if (fontSet.contains(font)) { - found.add(font); - } - } - if (found.size() == PREFERRED_FONTS.length) { - filteredFonts = PREFERRED_FONTS; - } else if (found.size() > 0) { - filteredFonts = new String[found.size()]; - for (int i = 0; i < found.size(); i++) { - filteredFonts[i] = found.get(i); - } - } else { - LOG.warn("Can't found any preferred fonts for smali, use all available."); - filteredFonts = env.getAvailableFontFamilyNames(); - } - } - return filteredFonts; - } -} diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java index 38928c683..96adbc040 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java @@ -44,8 +44,6 @@ import org.slf4j.LoggerFactory; import com.google.gson.GsonBuilder; import com.google.gson.JsonObject; -import say.swing.JFontChooser; - import jadx.api.CommentsLevel; import jadx.api.DecompilationMode; import jadx.api.JadxArgs; @@ -63,6 +61,7 @@ import jadx.gui.settings.JadxUpdateChannel; import jadx.gui.settings.LineNumbersMode; import jadx.gui.settings.XposedCodegenLanguage; import jadx.gui.settings.ui.cache.CacheSettingsGroup; +import jadx.gui.settings.ui.font.JadxFontDialog; import jadx.gui.settings.ui.plugins.PluginSettings; import jadx.gui.settings.ui.shortcut.ShortcutsSettingsGroup; import jadx.gui.ui.MainWindow; @@ -371,11 +370,9 @@ public class JadxSettingsWindow extends JDialog { fontBtn.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - JFontChooser fontChooser = new JFontChooser(); - fontChooser.setSelectedFont(settings.getFont()); - int result = fontChooser.showDialog(JadxSettingsWindow.this); - if (result == JFontChooser.OK_OPTION) { - Font font = fontChooser.getSelectedFont(); + 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(); @@ -387,11 +384,9 @@ public class JadxSettingsWindow extends JDialog { smaliFontBtn.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { - JFontChooser fontChooser = new JPreferredFontChooser(); - fontChooser.setSelectedFont(settings.getSmaliFont()); - int result = fontChooser.showDialog(JadxSettingsWindow.this); - if (result == JFontChooser.OK_OPTION) { - Font font = fontChooser.getSelectedFont(); + 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(); diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/font/FontChooserHack.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/font/FontChooserHack.java new file mode 100644 index 000000000..fd496104b --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/font/FontChooserHack.java @@ -0,0 +1,31 @@ +package jadx.gui.settings.ui.font; + +import java.lang.reflect.Field; + +import javax.swing.JCheckBox; + +import org.drjekyll.fontchooser.FontChooser; +import org.drjekyll.fontchooser.panes.FamilyPane; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class FontChooserHack { + private static final Logger LOG = LoggerFactory.getLogger(FontChooserHack.class); + + public static void setOnlyMonospace(FontChooser fontChooser) { + try { + FamilyPane familyPane = (FamilyPane) getPrivateField(fontChooser, "familyPane"); + JCheckBox monospacedCheckBox = (JCheckBox) getPrivateField(familyPane, "monospacedCheckBox"); + monospacedCheckBox.setSelected(true); + monospacedCheckBox.setEnabled(false); + } catch (Throwable e) { + LOG.debug("Failed to set only monospace check box", e); + } + } + + private static Object getPrivateField(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException { + Field f = obj.getClass().getDeclaredField(fieldName); + f.setAccessible(true); + return f.get(obj); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/font/JadxFontDialog.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/font/JadxFontDialog.java new file mode 100644 index 000000000..207496549 --- /dev/null +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/font/JadxFontDialog.java @@ -0,0 +1,86 @@ +package jadx.gui.settings.ui.font; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JPanel; +import javax.swing.WindowConstants; + +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 { + private static final long serialVersionUID = 7609857698785777587L; + + private final FontChooser fontChooser = new FontChooser(); + private final JadxSettings settings; + private boolean selected = false; + + public JadxFontDialog(JadxSettingsWindow settingsWindow, String title) { + super(settingsWindow, title, true); + settings = settingsWindow.getMainWindow().getSettings(); + initComponents(); + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + if (!settings.loadWindowPos(this)) { + pack(); + } + } + + public @Nullable Font select(Font currentFont, boolean onlyMonospace) { + fontChooser.setSelectedFont(currentFont); + if (onlyMonospace) { + FontChooserHack.setOnlyMonospace(fontChooser); + } + setVisible(true); + Font selectedFont = fontChooser.getSelectedFont(); + if (selected && !selectedFont.equals(currentFont)) { + return selectedFont; + } + return null; + } + + private void initComponents() { + JPanel chooserPanel = new JPanel(); + chooserPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 0, 10)); + chooserPanel.setLayout(new BorderLayout(0, 10)); + chooserPanel.add(fontChooser); + + JPanel controlPanel = new JPanel(); + controlPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + controlPanel.setLayout(new FlowLayout(FlowLayout.TRAILING)); + + JButton okBtn = new JButton(); + okBtn.setText(NLS.str("common_dialog.ok")); + okBtn.setMnemonic('o'); + okBtn.addActionListener(event -> { + selected = true; + dispose(); + }); + + JButton cancelBtn = new JButton(); + cancelBtn.setText(NLS.str("common_dialog.cancel")); + cancelBtn.setMnemonic('c'); + cancelBtn.addActionListener(event -> dispose()); + + controlPanel.add(okBtn); + controlPanel.add(cancelBtn); + + add(chooserPanel); + add(controlPanel, BorderLayout.PAGE_END); + getRootPane().setDefaultButton(okBtn); + } + + @Override + public void dispose() { + settings.saveWindowPos(this); + super.dispose(); + } +}