From feb9cb07f348ad31fafd778db0723f6d31eaf231 Mon Sep 17 00:00:00 2001 From: rubn Date: Thu, 23 Oct 2025 11:54:18 +0200 Subject: [PATCH 1/3] :construction: UI ConfigPanel --- .../skidfuscator/obfuscator/gui/ConfigPanel.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java index 4e789dab..2c95e6bf 100644 --- a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java +++ b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java @@ -102,8 +102,12 @@ public ConfigPanel() { // Input file gbc.gridx = 0; gbc.gridy = 0; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; add(new JLabel("Input JAR:"), gbc); gbc.gridx = 1; + gbc.weightx = 1.0; // IMPORTANTE: el campo se expande + gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE: llena horizontal inputField = new JTextField(30); JLabel inputCheck = new JLabel("✗"); inputCheck.setForeground(new Color(255, 65, 54)); @@ -149,8 +153,12 @@ private void updateCheck() { // Output file gbc.gridx = 0; gbc.gridy = 1; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; add(new JLabel("Output JAR:"), gbc); gbc.gridx = 1; + gbc.weightx = 1.0; // IMPORTANTE: el campo se expande + gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE outputField = new JTextField(30); JLabel outputCheck = new JLabel("✗"); outputCheck.setForeground(new Color(255, 65, 54)); @@ -228,8 +236,12 @@ private void updateCheck() { // Libraries gbc.gridx = 0; gbc.gridy = 2; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; add(new JLabel("Libraries:"), gbc); gbc.gridx = 1; + gbc.weightx = 1.0; // IMPORTANTE: el campo se expande + gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE libsField = new JTextField(30); JLabel libsCheck = new JLabel("✗"); libsCheck.setForeground(new Color(255, 65, 54)); @@ -270,8 +282,12 @@ private void updateCheck() { // Runtime gbc.gridx = 0; gbc.gridy = 3; + gbc.weightx = 0.0; + gbc.fill = GridBagConstraints.NONE; add(new JLabel("Runtime:"), gbc); gbc.gridx = 1; + gbc.weightx = 1.0; // IMPORTANTE: el campo se expande + gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE runtimeField = new JTextField(30); // Check if JDK was previously downloaded From df9d529cbc0cfa71a822c71e2a2b879d47dc8ae2 Mon Sep 17 00:00:00 2001 From: rubn Date: Sun, 26 Oct 2025 22:22:43 +0100 Subject: [PATCH 2/3] :construction: cleanup --- .../obfuscator/gui/ConfigPanel.java | 575 ++++++++++-------- 1 file changed, 305 insertions(+), 270 deletions(-) diff --git a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java index 2c95e6bf..08f3aab3 100644 --- a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java +++ b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java @@ -15,42 +15,214 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; -public class ConfigPanel extends JPanel implements SkidPanel{ - private final JTextField inputField; - private final JTextField outputField; - private final JTextField libsField; - private final JTextField runtimeField; - private final JCheckBox debugBox; - private final SkidfuscatorConfig config; - private Observable runtimeInstalled = new Observable.SimpleObservable<>( +public class ConfigPanel extends JPanel implements SkidPanel { + + private static final String CHECK_LABEL = "checkLabel"; + private final JTextField inputField = new JTextField(); + private final JTextField outputField = new JTextField(); + private final JTextField libsField = new JTextField(); + private final JTextField runtimeField = new JTextField(); + private final JCheckBox debugBox = new JCheckBox("Debug Mode"); + // Load configuration + private static final SkidfuscatorConfig CONFIG = SkidfuscatorConfig.load(); + private final Observable runtimeInstalled = new Observable.SimpleObservable<>( JdkDownloader.isJdkDownloaded() ); + private static final int MARGIN_HORIZONTAL = 40; // Margen izquierdo y derecho + private static final int MARGIN_VERTICAL = 10; // Espaciado vertical entre componentes + private static final int LABEL_WIDTH = 100; // Ancho fijo para las etiquetas + private static final int BUTTON_PANEL_WIDTH = 150; // Ancho fijo para el panel de botones + private static final String SEGOE_UI = "Segoe UI"; + public ConfigPanel() { setLayout(new GridBagLayout()); - // Create compound border with titled border and empty border for padding setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createTitledBorder( - BorderFactory.createEtchedBorder(EtchedBorder.RAISED), - "Configuration", - javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, - javax.swing.border.TitledBorder.DEFAULT_POSITION, - new Font("Segoe UI", Font.BOLD, 16) - ), - BorderFactory.createEmptyBorder(20, 0, 10, 0) + BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(EtchedBorder.RAISED), + "Configuration", + javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, + javax.swing.border.TitledBorder.DEFAULT_POSITION, + new Font(SEGOE_UI, Font.BOLD, 16) + ), + BorderFactory.createEmptyBorder(20, 0, 10, 0) )); + // Input file + int currentRow = 0; + addConfigRow(currentRow++, "Input JAR:", inputField, createInputValidation(), false); + // Output file + addConfigRow(currentRow++, "Output JAR:", outputField, createOutputValidation(), false); + // Libraries + addConfigRow(currentRow++, "Libraries:", libsField, createLibsValidation(), true); + addRuntimeRow(currentRow++); + addCheckboxRow(currentRow++); + addSaveButtonRow(currentRow++); + createDescriptionAreaAndIndicatorPanel(currentRow++); + setupAutoSave(); + } + + /** + * Crea las constraints base con configuración común + */ + private GridBagConstraints createBaseConstraints() { + GridBagConstraints gbc = new GridBagConstraints(); + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.anchor = GridBagConstraints.WEST; + return gbc; + } + + /** + * Crea constraints para las etiquetas + */ + private GridBagConstraints createLabelConstraints(int row) { + GridBagConstraints gbc = createBaseConstraints(); + gbc.gridx = 0; + gbc.gridy = row; + gbc.weightx = 0; + gbc.insets = new Insets(MARGIN_VERTICAL, MARGIN_HORIZONTAL, MARGIN_VERTICAL, 10); + gbc.fill = GridBagConstraints.NONE; + return gbc; + } + + /** + * Crea constraints para los campos de texto + */ + private GridBagConstraints createFieldConstraints(int row) { + GridBagConstraints gbc = createBaseConstraints(); + gbc.gridx = 1; + gbc.gridy = row; + gbc.weightx = 1.0; + gbc.insets = new Insets(MARGIN_VERTICAL, 0, MARGIN_VERTICAL, 10); + return gbc; + } + + /** + * Crea constraints para el panel de botones + */ + private GridBagConstraints createButtonPanelConstraints(int row) { + GridBagConstraints gbc = createBaseConstraints(); + gbc.gridx = 2; + gbc.gridy = row; + gbc.weightx = 0; + gbc.fill = GridBagConstraints.NONE; + gbc.insets = new Insets(MARGIN_VERTICAL, 0, MARGIN_VERTICAL, MARGIN_HORIZONTAL); + return gbc; + } + + /** + * Añade una fila de configuración completa + */ + private void addConfigRow(int row, String labelText, JTextField field, + DocumentListener validator, boolean isDirectory) { + // Label + JLabel label = new JLabel(labelText); + label.setPreferredSize(new Dimension(LABEL_WIDTH, 25)); + add(label, createLabelConstraints(row)); + + // Field + field.getDocument().addDocumentListener(validator); + add(field, createFieldConstraints(row)); + + // Button panel + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 30)); + + JButton browseButton = createBrowseButton(field, isDirectory); + JLabel checkLabel = new JLabel("✗"); + checkLabel.setForeground(new Color(255, 65, 54)); + + // Store check label in field's client property for validator access + field.putClientProperty(CHECK_LABEL, checkLabel); + + buttonPanel.add(browseButton); + buttonPanel.add(Box.createHorizontalGlue()); + buttonPanel.add(checkLabel); + + add(buttonPanel, createButtonPanelConstraints(row)); + + // Load saved value if exists + loadSavedValue(field, validator); + } + + /** + * Añade la fila de runtime con botón de instalación + */ + private void addRuntimeRow(int row) { + // Label + JLabel label = new JLabel("Runtime:"); + label.setPreferredSize(new Dimension(LABEL_WIDTH, 25)); + add(label, createLabelConstraints(row)); + + // Field + add(runtimeField, createFieldConstraints(row)); + + // Button panel with install button + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 30)); + + JLabel downloadCheck = new JLabel("✗"); + downloadCheck.setForeground(new Color(255, 65, 54)); + + JButton downloadButton = new JButton("Install"); + + // Initialize runtime field + initializeRuntimeField(downloadButton, downloadCheck); + + downloadButton.addActionListener(e -> handleRuntimeDownload(downloadButton, downloadCheck)); + + buttonPanel.add(downloadButton); + buttonPanel.add(Box.createHorizontalGlue()); + buttonPanel.add(downloadCheck); + + add(buttonPanel, createButtonPanelConstraints(row)); + } + + /** + * Añade la fila de checkboxes + */ + private void addCheckboxRow(int row) { + JPanel checkboxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + + debugBox.setSelected(CONFIG.isDebugEnabled()); + checkboxPanel.add(debugBox); + + GridBagConstraints gbc = createBaseConstraints(); + gbc.gridx = 0; + gbc.gridy = row; + gbc.gridwidth = 3; + gbc.insets = new Insets(MARGIN_VERTICAL, MARGIN_HORIZONTAL, MARGIN_VERTICAL, MARGIN_HORIZONTAL); + add(checkboxPanel, gbc); + } + + /** + * Añade la fila del botón de guardado + */ + private void addSaveButtonRow(int row) { + JButton saveButton = new JButton("Save Settings"); + saveButton.addActionListener(e -> saveConfiguration()); + + GridBagConstraints gbc = createBaseConstraints(); + gbc.gridx = 0; + gbc.gridy = row; + gbc.gridwidth = 3; + gbc.anchor = GridBagConstraints.LINE_END; + gbc.insets = new Insets(MARGIN_VERTICAL, MARGIN_HORIZONTAL, MARGIN_VERTICAL, MARGIN_HORIZONTAL); + add(saveButton, gbc); + } + + private void createDescriptionAreaAndIndicatorPanel(int currentRow) { // Add description panel at the top JTextArea descriptionArea = new JTextArea( - "Configure your obfuscation settings below:\n\n" + - "• Input JAR: Select the Java archive (.jar) file you want to obfuscate\n" + - "• Output JAR: Choose where to save the obfuscated file (.jar, .apk, or .dex)\n" + - "• Libraries: (Optional) Directory containing dependency JARs needed by your application\n" + - "• Runtime: JDK runtime libraries required for compilation (auto-downloaded)\n" + - "• Debug Mode: Enable additional logging and debugging information\n\n" + "Configure your obfuscation settings below:\n\n" + + "• Input JAR: Select the Java archive (.jar) file you want to obfuscate\n" + + "• Output JAR: Choose where to save the obfuscated file (.jar, .apk, or .dex)\n" + + "• Libraries: (Optional) Directory containing dependency JARs needed by your application\n" + + "• Runtime: JDK runtime libraries required for compilation (auto-downloaded)\n" + + "• Debug Mode: Enable additional logging and debugging information\n\n" ); descriptionArea.setEditable(false); - descriptionArea.setFont(new Font("Segoe UI", Font.PLAIN, 12)); + descriptionArea.setFont(new Font(SEGOE_UI, Font.PLAIN, 12)); descriptionArea.setLineWrap(true); descriptionArea.setWrapStyleWord(true); descriptionArea.setBackground(null); @@ -63,15 +235,15 @@ public ConfigPanel() { // Add indicators with colored symbols JLabel validLabel = new JLabel("✓ Green checkmarks indicate valid configurations"); - validLabel.setFont(new Font("Segoe UI", Font.PLAIN, 12)); + validLabel.setFont(new Font(SEGOE_UI, Font.PLAIN, 12)); validLabel.setForeground(new Color(0x2ECC40)); JLabel errorLabel = new JLabel("✗ Red X marks indicate issues that need to be resolved"); - errorLabel.setFont(new Font("Segoe UI", Font.PLAIN, 12)); + errorLabel.setFont(new Font(SEGOE_UI, Font.PLAIN, 12)); errorLabel.setForeground(new Color(0xFF4136)); JLabel optionalLabel = new JLabel("● Orange dots indicate optional fields"); - optionalLabel.setFont(new Font("Segoe UI", Font.PLAIN, 12)); + optionalLabel.setFont(new Font(SEGOE_UI, Font.PLAIN, 12)); optionalLabel.setForeground(new Color(0xFF851B)); indicatorPanel.add(validLabel); @@ -80,51 +252,36 @@ public ConfigPanel() { indicatorPanel.add(Box.createVerticalStrut(5)); indicatorPanel.add(optionalLabel); - // Add components to panel - GridBagConstraints gbc = new GridBagConstraints(); - gbc.fill = GridBagConstraints.HORIZONTAL; - gbc.insets = new Insets(0, 5, 0, 5); + // Add description and indicators at the end + GridBagConstraints gbc = createBaseConstraints(); gbc.gridx = 0; - gbc.gridy = 20; + gbc.gridy = currentRow++; gbc.gridwidth = 3; + gbc.weighty = 0; // Don't expand vertically + gbc.insets = new Insets(20, MARGIN_HORIZONTAL, 0, MARGIN_HORIZONTAL); add(descriptionArea, gbc); - gbc.gridy = -1; - gbc.insets = new Insets(0, 5, 20, 5); + gbc.gridy = currentRow; + gbc.insets = new Insets(0, MARGIN_HORIZONTAL, 10, MARGIN_HORIZONTAL); add(indicatorPanel, gbc); + } - // Reset gridwidth for other components - gbc.gridwidth = 1; - gbc.gridy++; - - // Load configuration - config = SkidfuscatorConfig.load(); - - // Input file - gbc.gridx = 0; gbc.gridy = 0; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.NONE; - add(new JLabel("Input JAR:"), gbc); - gbc.gridx = 1; - gbc.weightx = 1.0; // IMPORTANTE: el campo se expande - gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE: llena horizontal - inputField = new JTextField(30); - JLabel inputCheck = new JLabel("✗"); - inputCheck.setForeground(new Color(255, 65, 54)); - DocumentListener inputListener = new DocumentListener() { + private DocumentListener createInputValidation() { + return new DocumentListener() { private void updateCheck() { + JLabel checkLabel = (JLabel) inputField.getClientProperty(CHECK_LABEL); boolean valid = new File(inputField.getText()).exists(); - inputCheck.setText(valid ? "✓" : "✗"); - inputCheck.setForeground(valid ? new Color(46, 204, 64) : new Color(255, 65, 54)); - System.out.println("Input valid: " + valid); - config.getValidInput().set(valid); + + checkLabel.setText(valid ? "✓" : "✗"); + checkLabel.setForeground(valid ? new Color(46, 204, 64) : new Color(255, 65, 54)); + CONFIG.getValidInput().set(valid); if (!valid) { StringBuilder tooltip = new StringBuilder(""); tooltip.append("
⚠ Warning: Invalid Input Configuration
"); tooltip.append("
Input file does not exist
"); tooltip.append(""); - + ToolTipManager.sharedInstance().setInitialDelay(0); ToolTipManager.sharedInstance().setDismissDelay(10000); inputField.setToolTipText(tooltip.toString()); @@ -136,55 +293,27 @@ private void updateCheck() { public void removeUpdate(DocumentEvent e) { updateCheck(); } public void changedUpdate(DocumentEvent e) { updateCheck(); } }; - inputField.getDocument().addDocumentListener(inputListener); - if (config.getLastInputPath() != null) { - inputField.setText(config.getLastInputPath()); - inputListener.insertUpdate(null); // Trigger initial validation - } - add(inputField, gbc); - gbc.gridx = 2; - JPanel inputButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - inputButtonPanel.setPreferredSize(new Dimension(150, 30)); - JButton inputBrowseButton = createBrowseButton(inputField, false); - inputButtonPanel.add(inputBrowseButton); - inputButtonPanel.add(Box.createHorizontalGlue()); // Push label to right - inputButtonPanel.add(inputCheck); - add(inputButtonPanel, gbc); + } - // Output file - gbc.gridx = 0; gbc.gridy = 1; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.NONE; - add(new JLabel("Output JAR:"), gbc); - gbc.gridx = 1; - gbc.weightx = 1.0; // IMPORTANTE: el campo se expande - gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE - outputField = new JTextField(30); - JLabel outputCheck = new JLabel("✗"); - outputCheck.setForeground(new Color(255, 65, 54)); - DocumentListener outputListener = new DocumentListener() { + private DocumentListener createOutputValidation() { + return new DocumentListener() { private void updateCheck() { + JLabel checkLabel = (JLabel) outputField.getClientProperty(CHECK_LABEL); final String output = outputField.getText(); File parent = new File(output).getParentFile(); - // [condition] must be valid file extension final boolean validEnd = output.endsWith(".jar") || output.endsWith(".apk") || output.endsWith(".dex"); - - // [condition] must not be input final boolean validInput = !inputField.getText().equals(output); boolean valid = parent != null && parent.exists() && validEnd && validInput; - outputCheck.setText(valid ? "✓" : "✗"); - outputCheck.setForeground(valid - ? new Color(46, 204, 64) - : new Color(255, 65, 54) - ); - // Set tooltip explaining validation failure + checkLabel.setText(valid ? "✓" : "✗"); + checkLabel.setForeground(valid ? new Color(46, 204, 64) : new Color(255, 65, 54)); + StringBuilder tooltip = new StringBuilder(""); tooltip.append("
⚠ Warning: Invalid Output Configuration
"); - + if (parent == null || !parent.exists()) { tooltip.append("
Output directory does not exist
"); } @@ -195,12 +324,11 @@ private void updateCheck() { tooltip.append("
Output file cannot be the same as input file
"); } tooltip.append(""); - config.getValidOutput().set(validInput); - + CONFIG.getValidOutput().set(validInput); + if (!valid) { ToolTipManager.sharedInstance().setInitialDelay(0); ToolTipManager.sharedInstance().setDismissDelay(10000); - outputField.setToolTipText(tooltip.toString()); } else { outputField.setToolTipText(null); @@ -210,201 +338,121 @@ private void updateCheck() { public void removeUpdate(DocumentEvent e) { updateCheck(); } public void changedUpdate(DocumentEvent e) { updateCheck(); } }; - outputField.getDocument().addDocumentListener(outputListener); - if (config.getLastOutputPath() != null) { - outputField.setText(config.getLastOutputPath()); - outputListener.insertUpdate(null); - } else if (config.getLastInputPath() != null || inputField.getText() != null) { - final String input = config.getLastInputPath() != null - ? config.getLastInputPath() - : inputField.getText(); - - outputField.setText(input.replace(".jar", "-obf.jar")); - outputListener.insertUpdate(null); - } else { - config.getValidOutput().set(false); - } - add(outputField, gbc); - gbc.gridx = 2; - JPanel outputButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - outputButtonPanel.setPreferredSize(new Dimension(150, 30)); - JButton outputBrowseButton = createBrowseButton(outputField, false); - outputButtonPanel.add(outputBrowseButton); - outputButtonPanel.add(Box.createHorizontalGlue()); - outputButtonPanel.add(outputCheck); - add(outputButtonPanel, gbc); + } - // Libraries - gbc.gridx = 0; gbc.gridy = 2; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.NONE; - add(new JLabel("Libraries:"), gbc); - gbc.gridx = 1; - gbc.weightx = 1.0; // IMPORTANTE: el campo se expande - gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE - libsField = new JTextField(30); - JLabel libsCheck = new JLabel("✗"); - libsCheck.setForeground(new Color(255, 65, 54)); - DocumentListener libsListener = new DocumentListener() { + private DocumentListener createLibsValidation() { + return new DocumentListener() { private void updateCheck() { + JLabel checkLabel = (JLabel) libsField.getClientProperty(CHECK_LABEL); boolean valid; if (libsField.getText().isEmpty()) { - valid = true; // Empty is valid - // Set orange dot for pending state - libsCheck.setText("●"); - libsCheck.setForeground(new Color(255, 140, 0)); // Orange color + valid = true; + checkLabel.setText("●"); + checkLabel.setForeground(new Color(255, 140, 0)); return; } else { File dir = new File(libsField.getText()); valid = dir.exists() && dir.isDirectory(); } - libsCheck.setText(valid ? "✓" : "✗"); - libsCheck.setForeground(valid ? new Color(46, 204, 64) : new Color(255, 65, 54)); + checkLabel.setText(valid ? "✓" : "✗"); + checkLabel.setForeground(valid ? new Color(46, 204, 64) : new Color(255, 65, 54)); } public void insertUpdate(DocumentEvent e) { updateCheck(); } public void removeUpdate(DocumentEvent e) { updateCheck(); } public void changedUpdate(DocumentEvent e) { updateCheck(); } }; - libsField.getDocument().addDocumentListener(libsListener); - if (config.getLastLibsPath() != null) { - libsField.setText(config.getLastLibsPath()); - libsListener.insertUpdate(null); + } + + private void loadSavedValue(JTextField field, DocumentListener validator) { + String savedValue = null; + + if (field == inputField) { + savedValue = CONFIG.getLastInputPath(); + } else if (field == outputField) { + savedValue = CONFIG.getLastOutputPath(); + if (savedValue == null && CONFIG.getLastInputPath() != null) { + savedValue = CONFIG.getLastInputPath().replace(".jar", "-obf.jar"); + } + } else if (field == libsField) { + savedValue = CONFIG.getLastLibsPath(); } - add(libsField, gbc); - gbc.gridx = 2; - JPanel libsButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - libsButtonPanel.setPreferredSize(new Dimension(150, 30)); - JButton libsBrowseButton = createBrowseButton(libsField, true); - libsButtonPanel.add(libsBrowseButton); - libsButtonPanel.add(Box.createHorizontalGlue()); - libsButtonPanel.add(libsCheck); - add(libsButtonPanel, gbc); - - // Runtime - gbc.gridx = 0; gbc.gridy = 3; - gbc.weightx = 0.0; - gbc.fill = GridBagConstraints.NONE; - add(new JLabel("Runtime:"), gbc); - gbc.gridx = 1; - gbc.weightx = 1.0; // IMPORTANTE: el campo se expande - gbc.fill = GridBagConstraints.HORIZONTAL; // IMPORTANTE - runtimeField = new JTextField(30); - - // Check if JDK was previously downloaded + + if (savedValue != null) { + field.setText(savedValue); + validator.insertUpdate(null); + } + } + + private void initializeRuntimeField(JButton downloadButton, JLabel downloadCheck) { try { String jmodPath = JdkDownloader.getCachedJmodPath(); runtimeField.setText(jmodPath); runtimeField.setEnabled(!JdkDownloader.isJdkDownloaded()); runtimeInstalled.set(JdkDownloader.isJdkDownloaded()); + + if (JdkDownloader.isJdkDownloaded()) { + downloadButton.setText("Installed"); + downloadButton.setEnabled(false); + downloadCheck.setText("✓"); + downloadCheck.setForeground(new Color(46, 204, 64)); + } } catch (IOException e) { - // Fallback to config - if (config.getLastRuntimePath() != null) { - if (config.getLastRuntimePath().isEmpty()) { + if (CONFIG.getLastRuntimePath() != null) { + if (CONFIG.getLastRuntimePath().isEmpty()) { runtimeField.setText(Jvm.getLibsPath()); runtimeField.setEnabled(false); runtimeInstalled.set(true); } else { - runtimeField.setText(config.getLastRuntimePath()); + runtimeField.setText(CONFIG.getLastRuntimePath()); } } } + } - add(runtimeField, gbc); - - // Add download button next to browse button - gbc.gridx = 2; - JPanel runtimeButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - JLabel downloadCheck = new JLabel("✗"); - downloadCheck.setForeground(new Color(255, 65, 54)); + private void handleRuntimeDownload(JButton downloadButton, JLabel downloadCheck) { + downloadButton.setEnabled(false); + downloadButton.setText("Downloading..."); - JButton downloadButton = new JButton("Install"); - runtimeButtonPanel.setPreferredSize(new Dimension(150, 30)); - - // Set initial button state based on JDK download status - if (JdkDownloader.isJdkDownloaded()) { - downloadButton.setText("Installed"); - downloadButton.setEnabled(false); - downloadCheck.setText("✓"); - downloadCheck.setForeground(new Color(46, 204, 64)); - runtimeInstalled.set(true); - } - - downloadButton.addActionListener(e -> { - downloadButton.setEnabled(false); - downloadButton.setText("Downloading..."); - - SwingWorker worker = new SwingWorker<>() { - @Override - protected String doInBackground() throws Exception { - return JdkDownloader.getJmodPath(); - } + SwingWorker worker = new SwingWorker<>() { + @Override + protected String doInBackground() throws Exception { + return JdkDownloader.getJmodPath(); + } - @Override - protected void done() { - try { - String path = get(); - runtimeField.setText(path); - runtimeField.setEnabled(false); - downloadButton.setText("Installed"); - downloadButton.setEnabled(false); - downloadCheck.setText("✓"); - downloadCheck.setForeground(new Color(46, 204, 64)); - runtimeInstalled.set(true); - - } catch (Exception ex) { - JOptionPane.showMessageDialog( + @Override + protected void done() { + try { + String path = get(); + runtimeField.setText(path); + runtimeField.setEnabled(false); + downloadButton.setText("Installed"); + downloadButton.setEnabled(false); + downloadCheck.setText("✓"); + downloadCheck.setForeground(new Color(46, 204, 64)); + runtimeInstalled.set(true); + } catch (Exception ex) { + JOptionPane.showMessageDialog( ConfigPanel.this, "Failed to download JDK: " + ex.getMessage(), "Download Error", JOptionPane.ERROR_MESSAGE - ); - downloadButton.setText("Install"); - downloadButton.setEnabled(true); - downloadCheck.setText("✗"); - downloadCheck.setForeground(new Color(255, 65, 54)); - runtimeInstalled.set(false); - } + ); + downloadButton.setText("Install"); + downloadButton.setEnabled(true); + downloadCheck.setText("✗"); + downloadCheck.setForeground(new Color(255, 65, 54)); + runtimeInstalled.set(false); } - }; - worker.execute(); - }); - runtimeButtonPanel.add(downloadButton); - runtimeButtonPanel.add(Box.createHorizontalGlue()); - runtimeButtonPanel.add(downloadCheck); - - // removing for now - //runtimeButtonPanel.add(createBrowseButton(runtimeField, false)); - add(runtimeButtonPanel, gbc); - - // Checkboxes - JPanel checkboxPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); - debugBox = new JCheckBox("Debug Mode"); - //phantomBox = new JCheckBox("Use Phantom"); - debugBox.setSelected(config.isDebugEnabled()); - //phantomBox.setSelected(config.isPhantomEnabled()); - checkboxPanel.add(debugBox); - //checkboxPanel.add(phantomBox); - - gbc.gridx = 0; gbc.gridy = 4; - gbc.gridwidth = 3; - add(checkboxPanel, gbc); - - // Add save button - JButton saveButton = new JButton("Save Settings"); - saveButton.addActionListener(e -> saveConfiguration()); - gbc.gridy = 5; - gbc.anchor = GridBagConstraints.LINE_END; - add(saveButton, gbc); - - // Add automatic save on field changes - setupAutoSave(); + } + }; + worker.execute(); } private JButton createBrowseButton(JTextField field, boolean isDirectory) { - JButton button = new JButton("Browse"); + final JButton button = new JButton("Browse"); button.addActionListener(e -> { JFileChooser chooser = new JFileChooser(field.getText() == null - ? config.getLastDirectory() + ? CONFIG.getLastDirectory() : field.getText() ); if (isDirectory) { @@ -413,7 +461,7 @@ private JButton createBrowseButton(JTextField field, boolean isDirectory) { int result = chooser.showOpenDialog(this); if (result == JFileChooser.APPROVE_OPTION) { field.setText(chooser.getSelectedFile().getAbsolutePath()); - config.setLastDirectory(chooser.getCurrentDirectory().getAbsolutePath()); + CONFIG.setLastDirectory(chooser.getCurrentDirectory().getAbsolutePath()); saveConfiguration(); } }); @@ -421,13 +469,10 @@ private JButton createBrowseButton(JTextField field, boolean isDirectory) { } private void setupAutoSave() { - // Add document listeners to all text fields inputField.getDocument().addDocumentListener(new AutoSaveDocumentListener(this::saveConfiguration)); outputField.getDocument().addDocumentListener(new AutoSaveDocumentListener(this::saveConfiguration)); libsField.getDocument().addDocumentListener(new AutoSaveDocumentListener(this::saveConfiguration)); runtimeField.getDocument().addDocumentListener(new AutoSaveDocumentListener(this::saveConfiguration)); - - // Add action listeners to checkboxes debugBox.addActionListener(e -> saveConfiguration()); } @@ -439,7 +484,7 @@ private void saveConfiguration() { .setLastLibsPath(libsField.getText()) .setLastRuntimePath(runtimeField.getText()) .setDebugEnabled(debugBox.isSelected()) - .setLastDirectory(config.getLastDirectory()) + .setLastDirectory(CONFIG.getLastDirectory()) .build(); newConfig.save(); }); @@ -451,17 +496,7 @@ private void saveConfiguration() { public String getLibsPath() { return libsField.getText(); } public String getRuntimePath() { return runtimeField.getText(); } public boolean isDebugEnabled() { return debugBox.isSelected(); } - public String getLibraryPath() { - // TODO: Add a library path field to the config panel - return null; - } - - public Observable getRuntimeInstalled() { - return runtimeInstalled; - } - - public SkidfuscatorConfig getConfig() { - return config; - } -} - + public String getLibraryPath() { return null; } + public Observable getRuntimeInstalled() { return runtimeInstalled; } + public SkidfuscatorConfig getConfig() { return CONFIG; } +} \ No newline at end of file From dc2b07bb7771691b870a565738106f7a7c9a8484 Mon Sep 17 00:00:00 2001 From: rubn Date: Mon, 27 Oct 2025 10:27:27 +0100 Subject: [PATCH 3/3] :construction: Added method createBorder. - set height to 35 --- .../obfuscator/gui/ConfigPanel.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java index 08f3aab3..4efe200b 100644 --- a/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java +++ b/dev.skidfuscator.client.standalone/src/main/java/dev/skidfuscator/obfuscator/gui/ConfigPanel.java @@ -11,6 +11,7 @@ import dev.skidfuscator.obfuscator.util.JdkDownloader; import dev.skidfuscator.obfuscator.util.Observable; +import javax.swing.border.CompoundBorder; import javax.swing.border.EtchedBorder; import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; @@ -38,16 +39,7 @@ public class ConfigPanel extends JPanel implements SkidPanel { public ConfigPanel() { setLayout(new GridBagLayout()); // Create compound border with titled border and empty border for padding - setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createTitledBorder( - BorderFactory.createEtchedBorder(EtchedBorder.RAISED), - "Configuration", - javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, - javax.swing.border.TitledBorder.DEFAULT_POSITION, - new Font(SEGOE_UI, Font.BOLD, 16) - ), - BorderFactory.createEmptyBorder(20, 0, 10, 0) - )); + setBorder(createBorder()); // Input file int currentRow = 0; addConfigRow(currentRow++, "Input JAR:", inputField, createInputValidation(), false); @@ -62,6 +54,19 @@ public ConfigPanel() { setupAutoSave(); } + private CompoundBorder createBorder() { + return BorderFactory.createCompoundBorder( + BorderFactory.createTitledBorder( + BorderFactory.createEtchedBorder(EtchedBorder.RAISED), + "Configuration", + javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, + javax.swing.border.TitledBorder.DEFAULT_POSITION, + new Font(SEGOE_UI, Font.BOLD, 16) + ), + BorderFactory.createEmptyBorder(20, 0, 10, 0) + ); + } + /** * Crea las constraints base con configuración común */ @@ -126,7 +131,7 @@ private void addConfigRow(int row, String labelText, JTextField field, // Button panel JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 30)); + buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 35)); JButton browseButton = createBrowseButton(field, isDirectory); JLabel checkLabel = new JLabel("✗"); @@ -159,7 +164,7 @@ private void addRuntimeRow(int row) { // Button panel with install button JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); - buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 30)); + buttonPanel.setPreferredSize(new Dimension(BUTTON_PANEL_WIDTH, 35)); JLabel downloadCheck = new JLabel("✗"); downloadCheck.setForeground(new Color(255, 65, 54));