Skip to content

Commit

Permalink
Allow specifying a default action for the launcher
Browse files Browse the repository at this point in the history
Will be used when no arguments are provided. Ignored when invoked via javaw which will always open the GUI.
  • Loading branch information
Col-E committed Mar 30, 2024
1 parent e709f6e commit 8678073
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 28 deletions.
45 changes: 28 additions & 17 deletions src/main/java/software/coley/recaf/launch/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import software.coley.recaf.launch.info.JavaFxVersion;
import software.coley.recaf.launch.info.RecafVersion;
import software.coley.recaf.launch.info.SystemInformation;
import software.coley.recaf.launch.util.Config;

import javax.swing.*;
import java.util.Map;
Expand All @@ -25,25 +26,35 @@ public static void main(String[] args) {
// Always dump info first so the log file generates with system information that can be used to diagnose problems.
logger.info(dumpInfo());

// Check if user tried to run by double-clicking the jar instead of running from a console.
// If so, open the GUI.
boolean noArguments = (args == null || args.length == 0);
if (noArguments && System.console() == null) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable ignored) {
// Use the default ugly LaF then...
// Handle when no arguments are passed.
if (args == null || args.length == 0) {
// If there is no console instance, we've likely been launched via 'javaw'.
// Since there is no console to work with it only makes sense to open the GUI.
if (System.console() == null) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable ignored) {
// Use the default ugly LaF then...
}

new LauncherWindow().setVisible(true);
return;
}

new LauncherWindow().setVisible(true);
return;
} else if (noArguments) {
logger.info("\n" +
"===============================================================\n" +
"Seems like you didn't provide any launch arguments.\n" +
"You can open the GUI by running with 'javaw' instead of 'java'.\n" +
"If you meant to provide launch arguments, their usage is below.\n" +
"===============================================================\n\n");
// If the user has specified a default action, reset the args to that.
// Otherwise, tell
String defaultAction = Config.getInstance().getDefaultAction();
if (defaultAction != null) {
args = new String[]{defaultAction};
} else {
logger.info("\n" +
"===============================================================\n" +
"You did not provide any launch arguments, or specify a default" +
"to run in the launcher config.\n\n" +
"You can open the GUI by running with 'javaw' instead of 'java'.\n" +
"If you meant to provide launch arguments, their usage is below.\n" +
"===============================================================\n\n");
}
}

// Run the console commands.
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/software/coley/recaf/launch/commands/Root.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
* Root command. Registers the other commands.
*/
@Command(name = "<launcher>", subcommands = {
Auto.class, Compatibility.class, UpdateJavaFX.class, UpdateRecaf.class, UpdateRecafFromCI.class, GetVersion.class, Run.class
Auto.class, Compatibility.class, UpdateJavaFX.class, UpdateRecaf.class, UpdateRecafFromCI.class,
GetVersion.class, Run.class, SetDefaultAction.class
})
public class Root implements Callable<Void> {
private static final Logger logger = LoggerFactory.getLogger(Root.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package software.coley.recaf.launch.commands;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
import software.coley.recaf.launch.util.Config;

import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;

/**
* Command for specifying a default action to run, which will be used when invoking the launcher with no arguments
* in any following execution.
*/
@Command(name = "set-default-action", description = "Allows specifying a default action to run when no arguments are specified. " +
"For commands with spaces in them, surround the whole command with quotes.")
public class SetDefaultAction implements Callable<Void> {
private static final Logger logger = LoggerFactory.getLogger(SetDefaultAction.class);

@Parameters(index = "0", description = "The action to run. Should match one of the launcher commands.")
private String action;

@Override
public Void call() {
if ("set-default-action".equals(action)) {
logger.error("You cannot set the default action to be a recursive setting of the default action");
return null;
}

// Collect commands.
Set<String> commandNames = new TreeSet<>();
Command rootCommand = Root.class.getDeclaredAnnotation(Command.class);
Class<?>[] subcommands = rootCommand.subcommands();
for (Class<?> subcommand : subcommands) {
commandNames.add(subcommand.getDeclaredAnnotation(Command.class).name());
}

// Set it if it matches.
if (commandNames.contains(action)) {
Config.getInstance().setDefaultAction(action);
} else {
logger.error("The value '" + action + "' did not match any existing command name.\n" +
"The available commands are:\n" +
" - " + String.join("\n - ", commandNames));
}

return null;
}
}
83 changes: 76 additions & 7 deletions src/main/java/software/coley/recaf/launch/gui/LauncherWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import software.coley.recaf.launch.commands.UpdateRecafFromCI;
import software.coley.recaf.launch.info.JavaFxVersion;
import software.coley.recaf.launch.info.RecafVersion;
import software.coley.recaf.launch.util.Config;
import software.coley.recaf.launch.util.UpdateResult;

import javax.swing.*;
Expand All @@ -16,12 +17,13 @@
import java.util.EnumSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
* Basic launcher window with buttons to update Recaf and its dependencies.
*/
public class LauncherWindow extends JFrame {
private boolean isInitialized;

private final ExecutorService service = Executors.newCachedThreadPool(r -> {
Thread t = new Thread(r);
t.setDaemon(true);
Expand All @@ -35,7 +37,10 @@ public LauncherWindow() {

updateJavafxVersionLabel();
updateRecafVersionLabel();
updateDefaultAction();
compatibilityCheck();

isInitialized = true;
}

/**
Expand Down Expand Up @@ -116,8 +121,55 @@ private void compatibilityCheck() {
}

/**
* Runs Recaf.
* Updates the selected {@link #defaultActionComboBox} based on the current {@link Config#getDefaultAction()} value.
*/
private void updateDefaultAction() {
String tooltip = "<html>" +
"<head><style>\n" +
".code {\n" +
" font-family: monospace;\n" +
" font-weight: bold;\n" +
" background-color: rgba(0, 0, 0, 0.1);\n" +
" background-image: none;\n" +
" border-color: rgba(140, 130, 115, 0.8);\n" +
"}" +
"</style></head>" +
"The default action will only be used when executed from <span class=\"code\">java</span>." +
"<p/>" +
"Using <span class=\"code\">javaw</span> will always open this user interface.</html>";
defaultActionComboBox.setToolTipText(tooltip);
defaultActionLabel.setToolTipText(tooltip);

String defaultAction = Config.getInstance().getDefaultAction();
if (defaultAction == null) return;
else if (defaultAction.startsWith("auto")) defaultActionComboBox.setSelectedIndex(1);
else if (defaultAction.startsWith("run")) defaultActionComboBox.setSelectedIndex(2);
}

/**
* Update {@link Config#getDefaultAction()}.
*/
private void onDefaultActionChanged() {
if (!isInitialized) return;
String defaultAction;
int selectedIndex = defaultActionComboBox.getSelectedIndex();
switch (selectedIndex) {
case 1:
defaultAction = "auto";
break;
case 2:
defaultAction = "run";
break;
default: // covers '0'
defaultAction = null;
break;
}
Config.getInstance().setDefaultAction(defaultAction);
}

/**
* Runs Recaf.
*/
private void launch() {
Run.RunResult runResult = Run.run(false, null);
if (runResult.isSuccess())
Expand All @@ -140,6 +192,8 @@ private void initComponents() {
compatibilityLabel = new JLabel();
compatibilityValueLabel = new JLabel();
compatibilityCheckButton = new JButton();
defaultActionLabel = new JLabel();
defaultActionComboBox = new JComboBox<>();
actionsPanel = new JPanel();
launchButton = new JButton();
outputs = new JPanel();
Expand All @@ -161,14 +215,14 @@ private void initComponents() {
inputs.setBorder(new EmptyBorder(8, 8, 8, 8));
inputs.setLayout(new FormLayout(
"default, $lcgap, default:grow, $lcgap, default",
"3*(default, $lgap), default"));
"4*(default, $lgap), default"));

//---- recafVersionLabel ----
recafVersionLabel.setText("Recaf Version:");
inputs.add(recafVersionLabel, CC.xy(1, 1));

//---- recafVersionValueLabel ----
recafVersionValueLabel.setText("<pending...>");
recafVersionValueLabel.setText("UNKNOWN");
inputs.add(recafVersionValueLabel, CC.xy(3, 1));

//---- recafVersionUpdateButton ----
Expand All @@ -181,7 +235,7 @@ private void initComponents() {
inputs.add(jfxVersionLabel, CC.xy(1, 3));

//---- jfxVersionValueLabel ----
jfxVersionValueLabel.setText("<pending...>");
jfxVersionValueLabel.setText("UNKNOWN");
inputs.add(jfxVersionValueLabel, CC.xy(3, 3));

//---- jfxVersionUpdateButton ----
Expand All @@ -194,14 +248,27 @@ private void initComponents() {
inputs.add(compatibilityLabel, CC.xy(1, 5));

//---- compatibilityValueLabel ----
compatibilityValueLabel.setText("<pending...>");
compatibilityValueLabel.setText("UNKNOWN");
inputs.add(compatibilityValueLabel, CC.xy(3, 5));

//---- compatibilityCheckButton ----
compatibilityCheckButton.setText("Recheck");
compatibilityCheckButton.addActionListener(e -> compatibilityCheck());
inputs.add(compatibilityCheckButton, CC.xy(5, 5));

//---- defaultActionLabel ----
defaultActionLabel.setText("Default action:");
inputs.add(defaultActionLabel, CC.xy(1, 7));

//---- defaultActionComboBox ----
defaultActionComboBox.setModel(new DefaultComboBoxModel<>(new String[] {
"<No action>",
"Update then run Recaf",
"Run Recaf"
}));
defaultActionComboBox.addItemListener(e -> onDefaultActionChanged());
inputs.add(defaultActionComboBox, CC.xywh(3, 7, 3, 1));

//======== actionsPanel ========
{
actionsPanel.setBorder(new EmptyBorder(12, 0, 0, 0));
Expand All @@ -215,7 +282,7 @@ private void initComponents() {
launchButton.addActionListener(e -> launch());
actionsPanel.add(launchButton, CC.xy(1, 1));
}
inputs.add(actionsPanel, CC.xywh(1, 7, 5, 1));
inputs.add(actionsPanel, CC.xywh(1, 9, 5, 1));
}
contentPane.add(inputs, CC.xy(1, 1));

Expand Down Expand Up @@ -254,6 +321,8 @@ private void initComponents() {
private JLabel compatibilityLabel;
private JLabel compatibilityValueLabel;
private JButton compatibilityCheckButton;
private JLabel defaultActionLabel;
private JComboBox<String> defaultActionComboBox;
private JPanel actionsPanel;
private JButton launchButton;
private JPanel outputs;
Expand Down
27 changes: 24 additions & 3 deletions src/main/java/software/coley/recaf/launch/gui/LauncherWindow.jfd
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
JFDML JFormDesigner: "8.1.1.0.298" Java: "17.0.7" encoding: "UTF-8"
JFDML JFormDesigner: "8.2.1.0.348" Java: "17.0.9" encoding: "UTF-8"

new FormModel {
contentType: "form/swing"
Expand All @@ -14,7 +14,7 @@ new FormModel {
"preferredSize": new java.awt.Dimension( 420, 280 )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class com.jgoodies.forms.layout.FormLayout ) {
"$columnSpecs": "default, labelcompgap, default:grow, labelcompgap, default"
"$rowSpecs": "default, linegap, default, linegap, default, linegap, default"
"$rowSpecs": "default, linegap, default, linegap, default, linegap, default, linegap, default"
} ) {
name: "inputs"
"border": new javax.swing.border.EmptyBorder( 8, 8, 8, 8 )
Expand Down Expand Up @@ -81,6 +81,27 @@ new FormModel {
"gridX": 5
"gridY": 5
} )
add( new FormComponent( "javax.swing.JLabel" ) {
name: "defaultActionLabel"
"text": "Default action:"
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 1
"gridY": 7
} )
add( new FormComponent( "javax.swing.JComboBox" ) {
name: "defaultActionComboBox"
"model": new javax.swing.DefaultComboBoxModel {
selectedItem: "<No action>"
addElement( "<No action>" )
addElement( "Update then run Recaf" )
addElement( "Run Recaf" )
}
addEvent( new FormEvent( "java.awt.event.ItemListener", "itemStateChanged", "onDefaultActionChanged", false ) )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridX": 3
"gridY": 7
"gridWidth": 3
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class com.jgoodies.forms.layout.FormLayout ) {
"$columnSpecs": "center:default:grow"
"$rowSpecs": "default"
Expand All @@ -97,7 +118,7 @@ new FormModel {
"gridY": 1
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
"gridY": 7
"gridY": 9
"gridWidth": 5
} )
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
Expand Down

0 comments on commit 8678073

Please sign in to comment.