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());
}
}
}