Skip to content

Commit

Permalink
Improve the GUI (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matyrobbrt authored Jan 2, 2024
1 parent 1b37590 commit bcc2055
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 96 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.7'
testImplementation(platform('org.junit:junit-bom:5.7.2'))
testImplementation('org.junit.jupiter:junit-jupiter')
compileOnly 'org.jetbrains:annotations:24.1.0'
}

test {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ private static boolean download(ProgressCallback monitor, Mirror mirror, Downloa
try {
URLConnection connection = getConnection(url);
if (connection != null) {
Files.copy(connection.getInputStream(), target.toPath(), StandardCopyOption.REPLACE_EXISTING);
Files.copy(monitor.wrapStepDownload(connection), target.toPath(), StandardCopyOption.REPLACE_EXISTING);

if (download.getSha1() != null) {
String sha1 = getSha1(target);
Expand Down
130 changes: 70 additions & 60 deletions src/main/java/net/minecraftforge/installer/InstallerPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,61 +18,50 @@
*/
package net.minecraftforge.installer;

import java.awt.BorderLayout;
import net.minecraftforge.installer.actions.Action;
import net.minecraftforge.installer.actions.ActionCanceledException;
import net.minecraftforge.installer.actions.Actions;
import net.minecraftforge.installer.actions.ProgressCallback;
import net.minecraftforge.installer.json.InstallV1;
import net.minecraftforge.installer.json.OptionalLibrary;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;
import javax.swing.border.LineBorder;
import java.awt.Color;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Font;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.SwingConstants;
import javax.swing.border.LineBorder;

import net.minecraftforge.installer.actions.Action;
import net.minecraftforge.installer.actions.ActionCanceledException;
import net.minecraftforge.installer.actions.Actions;
import net.minecraftforge.installer.actions.ProgressCallback;
import net.minecraftforge.installer.json.Install;
import net.minecraftforge.installer.json.InstallV1;
import net.minecraftforge.installer.json.OptionalLibrary;
import net.minecraftforge.installer.json.Util;

@SuppressWarnings("unused")
public class InstallerPanel extends JPanel {
private static final long serialVersionUID = 1L;
Expand All @@ -88,6 +77,8 @@ public class InstallerPanel extends JPanel {
private List<OptionalListEntry> optionals = new ArrayList<>();
private Map<String, Function<ProgressCallback, Action>> actions = new HashMap<>();

private Optional<JButton> proceedButton = Optional.empty();

private final InstallV1 profile;
private final File installer;

Expand All @@ -101,17 +92,15 @@ public void actionPerformed(ActionEvent e)
JFileChooser dirChooser = new JFileChooser();
dirChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
dirChooser.setFileHidingEnabled(false);
dirChooser.setDialogTitle("Select installation directory");
dirChooser.setApproveButtonText("Select");
dirChooser.ensureFileIsVisible(targetDir);
dirChooser.setSelectedFile(targetDir);

int response = dirChooser.showOpenDialog(InstallerPanel.this);
switch (response)
{
case JFileChooser.APPROVE_OPTION:
if (response == JFileChooser.APPROVE_OPTION) {
targetDir = dirChooser.getSelectedFile();
updateFilePath();
break;
default:
break;
}
}
}
Expand Down Expand Up @@ -178,10 +167,19 @@ public InstallerPanel(File targetDir, InstallV1 profile, File installer)
tag.setAlignmentX(CENTER_ALIGNMENT);
tag.setAlignmentY(CENTER_ALIGNMENT);
logoSplash.add(tag);
tag = new JLabel(profile.getVersion());
tag.setAlignmentX(CENTER_ALIGNMENT);
tag.setAlignmentY(CENTER_ALIGNMENT);
logoSplash.add(tag);

{
// The version is a box that has a first label that is non-bold
final Box version = Box.createHorizontalBox();
version.add(new JLabel("Version: "));
tag = new JLabel(profile.getVersion());
// and a bold part which represents the actual version
tag.setFont(tag.getFont().deriveFont(Font.BOLD));
version.add(tag);
version.setAlignmentX(CENTER_ALIGNMENT);
version.setAlignmentY(CENTER_ALIGNMENT);
logoSplash.add(version);
}

logoSplash.setAlignmentX(CENTER_ALIGNMENT);
logoSplash.setAlignmentY(TOP_ALIGNMENT);
Expand All @@ -192,12 +190,6 @@ public InstallerPanel(File targetDir, InstallV1 profile, File installer)
sponsorPanel.setAlignmentX(CENTER_ALIGNMENT);
sponsorPanel.setAlignmentY(CENTER_ALIGNMENT);

// sponsorLogo = new JLabel();
// sponsorLogo.setSize(50, 20);
// sponsorLogo.setAlignmentX(CENTER_ALIGNMENT);
// sponsorLogo.setAlignmentY(CENTER_ALIGNMENT);
// sponsorPanel.add(sponsorLogo);

sponsorButton = new JButton();
sponsorButton.setAlignmentX(CENTER_ALIGNMENT);
sponsorButton.setAlignmentY(CENTER_ALIGNMENT);
Expand All @@ -211,7 +203,7 @@ public InstallerPanel(File targetDir, InstallV1 profile, File installer)
choiceButtonGroup = new ButtonGroup();

JPanel choicePanel = new JPanel();
choicePanel.setLayout(new BoxLayout(choicePanel, BoxLayout.Y_AXIS));
choicePanel.setLayout(new BoxLayout(choicePanel, BoxLayout.PAGE_AXIS));
boolean first = true;
SelectButtonAction sba = new SelectButtonAction();
for (Actions action : Actions.values())
Expand All @@ -228,12 +220,20 @@ public InstallerPanel(File targetDir, InstallV1 profile, File installer)
radioButton.setSelected(first);
radioButton.setAlignmentX(LEFT_ALIGNMENT);
radioButton.setAlignmentY(CENTER_ALIGNMENT);
radioButton.setSize(15, 15);
// The default gap of 4 is too small for the size of the buttons, so almost triple the gap
// to avoid clipping and improve readability
radioButton.setIconTextGap(10);
// Pad the button 5 pixels everywhere to avoid overlapping
radioButton.setMargin(new Insets(3, 3, 3, 3));
choiceButtonGroup.add(radioButton);
choicePanel.add(radioButton);
// Add a pixel between the buttons that ensures vertical separation and prevents clipping
choicePanel.add(Box.createRigidArea(new Dimension(1, 1)));
first = false;
}

choicePanel.setAlignmentX(RIGHT_ALIGNMENT);
choicePanel.setAlignmentX(CENTER_ALIGNMENT);
choicePanel.setAlignmentY(CENTER_ALIGNMENT);
add(choicePanel);

Expand Down Expand Up @@ -319,14 +319,13 @@ public void mouseMoved(MouseEvent event)
this.targetDir = targetDir;
selectedDirText = new JTextField();
selectedDirText.setEditable(false);
selectedDirText.setToolTipText("Path to minecraft");
selectedDirText.setToolTipText("Path to the Minecraft installation directory");
selectedDirText.setColumns(30);
// homeDir.setMaximumSize(homeDir.getPreferredSize());
entryPanel.add(selectedDirText);
JButton dirSelect = new JButton();
dirSelect.setAction(new FileSelectAction());
dirSelect.setText("...");
dirSelect.setToolTipText("Select an alternative minecraft directory");
dirSelect.setToolTipText("Select an alternative Minecraft directory");
entryPanel.add(dirSelect);

entryPanel.setAlignmentX(LEFT_ALIGNMENT);
Expand Down Expand Up @@ -385,13 +384,15 @@ private void updateFilePath()
selectedDirText.setForeground(null);
infoLabel.setVisible(false);
fileEntryPanel.setBorder(null);
proceedButton.ifPresent(button -> button.setEnabled(true));
}
else
{
selectedDirText.setForeground(Color.RED);
fileEntryPanel.setBorder(new LineBorder(Color.RED));
infoLabel.setText("<html>"+action.getFileError(targetDir)+"</html>");
infoLabel.setVisible(true);
proceedButton.ifPresent(button -> button.setEnabled(false));
}
if (dialog!=null)
{
Expand All @@ -404,7 +405,16 @@ public void run(ProgressCallback monitor)
{
JOptionPane optionPane = new JOptionPane(this, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);

dialog = optionPane.createDialog("Mod system installer");
// Attempt to change the OK button to a Proceed button
// Use index 1 (the buttons panel) as 0 is this panel
proceedButton = Arrays.stream(((JPanel) optionPane.getComponents()[1]).getComponents())
.filter(comp -> comp instanceof JButton)
.map(JButton.class::cast)
.filter(btn -> btn.getText().equals("OK"))
.findFirst();
proceedButton.ifPresent(button -> button.setText("Proceed"));

dialog = optionPane.createDialog("NeoForge installer");
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
int result = (Integer) (optionPane.getValue() != null ? optionPane.getValue() : -1);
Expand All @@ -422,7 +432,7 @@ public void run(ProgressCallback monitor)
prog.toFront();
if (action.run(targetDir, optPred, installer)) {
prog.start("Finished!");
prog.progress(1);
prog.getGlobalProgress().percentageProgress(1);
JOptionPane.showMessageDialog(null, action.getSuccessMessage(), "Complete", JOptionPane.INFORMATION_MESSAGE);
}
} catch (ActionCanceledException e) {
Expand Down
Loading

0 comments on commit bcc2055

Please sign in to comment.