package jadx.gui.settings; import jadx.gui.ui.MainWindow; import jadx.gui.utils.NLS; import say.swing.JFontChooser; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SwingConstants; import javax.swing.WindowConstants; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import java.awt.BorderLayout; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class JadxSettingsWindow extends JDialog { private static final long serialVersionUID = -1804570470377354148L; private static final Logger LOG = LoggerFactory.getLogger(JadxSettingsWindow.class); private final MainWindow mainWindow; private final JadxSettings settings; private final String startSettings; private boolean needReload = false; public JadxSettingsWindow(MainWindow mainWindow, JadxSettings settings) { this.mainWindow = mainWindow; this.settings = settings; this.startSettings = JadxSettingsAdapter.makeString(settings); initUI(); setTitle(NLS.str("preferences.title")); setSize(400, 550); setLocationRelativeTo(null); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); setModalityType(ModalityType.APPLICATION_MODAL); pack(); } private void initUI() { JPanel panel = new JPanel(); panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS)); panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); panel.add(makeDeobfuscationGroup()); panel.add(makeDecompilationGroup()); panel.add(makeEditorGroup()); panel.add(makeOtherGroup()); JButton saveBtn = new JButton(NLS.str("preferences.save")); saveBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { settings.sync(); if (needReload) { mainWindow.reOpenFile(); } dispose(); } }); JButton cancelButton = new JButton(NLS.str("preferences.cancel")); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { JadxSettingsAdapter.fill(settings, startSettings); dispose(); } }); JButton resetBtn = new JButton(NLS.str("preferences.reset")); resetBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { int res = JOptionPane.showConfirmDialog( JadxSettingsWindow.this, NLS.str("preferences.reset_message"), NLS.str("preferences.reset_title"), JOptionPane.YES_NO_OPTION); if (res == JOptionPane.YES_OPTION) { String defaults = JadxSettingsAdapter.makeString(new JadxSettings()); JadxSettingsAdapter.fill(settings, defaults); getContentPane().removeAll(); initUI(); pack(); repaint(); } } }); JPanel buttonPane = new JPanel(); buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS)); buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10)); buttonPane.add(resetBtn); buttonPane.add(Box.createHorizontalGlue()); buttonPane.add(saveBtn); buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); buttonPane.add(cancelButton); Container contentPane = getContentPane(); contentPane.add(panel, BorderLayout.CENTER); contentPane.add(buttonPane, BorderLayout.PAGE_END); getRootPane().setDefaultButton(saveBtn); } private SettingsGroup makeDeobfuscationGroup() { JCheckBox deobfOn = new JCheckBox(); deobfOn.setSelected(settings.isDeobfuscationOn()); deobfOn.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setDeobfuscationOn(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); JCheckBox deobfForce = new JCheckBox(); deobfForce.setSelected(settings.isDeobfuscationForceSave()); deobfForce.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setDeobfuscationForceSave(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); final JSpinner minLen = new JSpinner(); minLen.setValue(settings.getDeobfuscationMinLength()); minLen.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { settings.setDeobfuscationMinLength((Integer) minLen.getValue()); needReload(); } }); final JSpinner maxLen = new JSpinner(); maxLen.setValue(settings.getDeobfuscationMaxLength()); maxLen.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { settings.setDeobfuscationMaxLength((Integer) maxLen.getValue()); needReload(); } }); JCheckBox deobfSourceAlias = new JCheckBox(); deobfSourceAlias.setSelected(settings.useSourceNameAsClassAlias()); deobfSourceAlias.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setUseSourceNameAsClassAlias(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); SettingsGroup deobfGroup = new SettingsGroup(NLS.str("preferences.deobfuscation")); deobfGroup.addRow(NLS.str("preferences.deobfuscation_on"), deobfOn); deobfGroup.addRow(NLS.str("preferences.deobfuscation_force"), deobfForce); deobfGroup.addRow(NLS.str("preferences.deobfuscation_min_len"), minLen); deobfGroup.addRow(NLS.str("preferences.deobfuscation_max_len"), maxLen); deobfGroup.addRow(NLS.str("preferences.deobfuscation_source_alias"), deobfSourceAlias); deobfGroup.end(); return deobfGroup; } private SettingsGroup makeEditorGroup() { JButton fontBtn = new JButton(NLS.str("preferences.select_font")); 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(); LOG.info("Selected Font : {}", font); settings.setFont(font); mainWindow.updateFont(font); } } }); SettingsGroup other = new SettingsGroup(NLS.str("preferences.editor")); other.addRow(NLS.str("preferences.font"), fontBtn); return other; } private SettingsGroup makeDecompilationGroup() { JCheckBox fallback = new JCheckBox(); fallback.setSelected(settings.isFallbackMode()); fallback.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setFallbackMode(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); JCheckBox showInconsistentCode = new JCheckBox(); showInconsistentCode.setSelected(settings.isShowInconsistentCode()); showInconsistentCode.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setShowInconsistentCode(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); JCheckBox resourceDecode = new JCheckBox(); resourceDecode.setSelected(settings.isSkipResources()); resourceDecode.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setSkipResources(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); final JSpinner threadsCount = new JSpinner(); threadsCount.setValue(settings.getThreadsCount()); threadsCount.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { settings.setThreadsCount((Integer) threadsCount.getValue()); } }); JCheckBox autoStartJobs = new JCheckBox(); autoStartJobs.setSelected(settings.isAutoStartJobs()); autoStartJobs.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setAutoStartJobs(e.getStateChange() == ItemEvent.SELECTED); } }); JCheckBox escapeUnicode = new JCheckBox(); escapeUnicode.setSelected(settings.escapeUnicode()); escapeUnicode.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setEscapeUnicode(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); JCheckBox replaceConsts = new JCheckBox(); replaceConsts.setSelected(settings.isReplaceConsts()); replaceConsts.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setReplaceConsts(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); SettingsGroup other = new SettingsGroup(NLS.str("preferences.decompile")); other.addRow(NLS.str("preferences.threads"), threadsCount); other.addRow(NLS.str("preferences.start_jobs"), autoStartJobs); other.addRow(NLS.str("preferences.showInconsistentCode"), showInconsistentCode); other.addRow(NLS.str("preferences.escapeUnicode"), escapeUnicode); other.addRow(NLS.str("preferences.replaceConsts"), replaceConsts); other.addRow(NLS.str("preferences.fallback"), fallback); other.addRow(NLS.str("preferences.skipResourcesDecode"), resourceDecode); return other; } private SettingsGroup makeOtherGroup() { JCheckBox update = new JCheckBox(); update.setSelected(settings.isCheckForUpdates()); update.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setCheckForUpdates(e.getStateChange() == ItemEvent.SELECTED); } }); JCheckBox cfg = new JCheckBox(); cfg.setSelected(settings.isCFGOutput()); cfg.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setCfgOutput(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); JCheckBox rawCfg = new JCheckBox(); rawCfg.setSelected(settings.isRawCFGOutput()); rawCfg.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { settings.setRawCfgOutput(e.getStateChange() == ItemEvent.SELECTED); needReload(); } }); SettingsGroup other = new SettingsGroup(NLS.str("preferences.other")); other.addRow(NLS.str("preferences.check_for_updates"), update); other.addRow(NLS.str("preferences.cfg"), cfg); other.addRow(NLS.str("preferences.raw_cfg"), rawCfg); return other; } private void needReload() { needReload = true; } private static class SettingsGroup extends JPanel { private static final long serialVersionUID = -6487309975896192544L; private final GridBagConstraints c; private int row; public SettingsGroup(String title) { setBorder(BorderFactory.createTitledBorder(title)); setLayout(new GridBagLayout()); c = new GridBagConstraints(); c.insets = new Insets(5, 5, 5, 5); c.weighty = 1.0; } public void addRow(String label, JComponent comp) { c.gridy = row++; JLabel jLabel = new JLabel(label); jLabel.setLabelFor(comp); jLabel.setHorizontalAlignment(SwingConstants.LEFT); c.gridx = 0; c.gridwidth = 1; c.anchor = GridBagConstraints.LINE_START; c.weightx = 0.8; c.fill = GridBagConstraints.NONE; add(jLabel, c); c.gridx = 1; c.gridwidth = GridBagConstraints.REMAINDER; c.anchor = GridBagConstraints.CENTER; c.weightx = 0.2; c.fill = GridBagConstraints.HORIZONTAL; add(comp, c); } public void end() { add(Box.createVerticalGlue()); } } }