Add proper options dialog (I do GUI in Windowbuilder usually)

This commit is contained in:
comp500 2019-08-10 18:29:40 +01:00
parent dcf8d21aad
commit 54fd84a6d8
4 changed files with 246 additions and 11 deletions

View File

@ -109,16 +109,13 @@ public class Main {
// Start update process! // Start update process!
// TODO: start in SwingWorker? // TODO: start in SwingWorker?
try { try {
ui.executeManager(new Runnable(){ ui.executeManager(() -> {
@Override
public void run() {
try { try {
new UpdateManager(uOptions, ui); new UpdateManager(uOptions, ui);
} catch (Exception e) { } catch (Exception e) {
// TODO: better error message? // TODO: better error message?
ui.handleExceptionAndExit(e); ui.handleExceptionAndExit(e);
} }
}
}); });
} catch (Exception e) { } catch (Exception e) {
// TODO: better error message? // TODO: better error message?

View File

@ -4,6 +4,7 @@ import javax.swing.*;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import java.awt.*; import java.awt.*;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -161,8 +162,12 @@ public class InstallWindow implements IUserInterface {
} }
@Override @Override
public Future<Boolean> showOptions(List<IOptionDetails> option) { public Future<Boolean> showOptions(List<IOptionDetails> opts) {
return null; CompletableFuture<Boolean> future = new CompletableFuture<Boolean>();
OptionsSelectWindow dialog = new OptionsSelectWindow(opts, future);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
return future;
} }
} }

View File

@ -0,0 +1,33 @@
package link.infra.packwiz.installer.ui;
// Serves as a proxy for IOptionDetails, so that setOptionValue isn't called until OK is clicked
public class OptionTempHandler implements IOptionDetails {
private final IOptionDetails opt;
private boolean tempValue;
public OptionTempHandler(IOptionDetails opt) {
this.opt = opt;
tempValue = opt.getOptionValue();
}
public String getName() {
return opt.getName();
}
public String getOptionDescription() {
return opt.getOptionDescription();
}
public boolean getOptionValue() {
return tempValue;
}
public void setOptionValue(boolean value) {
tempValue = value;
}
public void finalise() {
opt.setOptionValue(tempValue);
}
}

View File

@ -0,0 +1,200 @@
package link.infra.packwiz.installer.ui;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class OptionsSelectWindow extends JDialog implements ActionListener {
private static final long serialVersionUID = 1L;
private final JPanel contentPanel = new JPanel();
private final JLabel lblOptionDescription;
private final OptionTableModel tableModel;
private final CompletableFuture<Boolean> future;
/**
* Create the dialog.
*/
public OptionsSelectWindow(List<IOptionDetails> optList, CompletableFuture<Boolean> future) {
tableModel = new OptionTableModel(optList);
this.future = future;
setModal(true);
setTitle("Select optional mods...");
setBounds(100, 100, 450, 300);
getContentPane().setLayout(new BorderLayout());
contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
getContentPane().add(contentPanel, BorderLayout.CENTER);
contentPanel.setLayout(new BorderLayout(0, 0));
{
JSplitPane splitPane = new JSplitPane();
splitPane.setResizeWeight(0.5);
contentPanel.add(splitPane);
{
JTable table = new JTable();
table.setShowVerticalLines(false);
table.setShowHorizontalLines(false);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.setShowGrid(false);
table.setModel(tableModel);
table.getColumnModel().getColumn(0).setResizable(false);
table.getColumnModel().getColumn(0).setPreferredWidth(15);
table.getColumnModel().getColumn(0).setMaxWidth(15);
table.getColumnModel().getColumn(1).setResizable(false);
table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
int i = table.getSelectedRow();
if (i > -1) {
lblOptionDescription.setText(tableModel.getDescription(i));
} else {
lblOptionDescription.setText("Select an option...");
}
}
});
table.setTableHeader(null);
JScrollPane scrollPane = new JScrollPane(table);
scrollPane.getViewport().setBackground(UIManager.getColor("List.background"));
scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
splitPane.setLeftComponent(scrollPane);
}
{
lblOptionDescription = new JLabel("Select an option...");
lblOptionDescription.setBackground(UIManager.getColor("List.background"));
lblOptionDescription.setOpaque(true);
lblOptionDescription.setVerticalAlignment(SwingConstants.TOP);
lblOptionDescription.setBorder(new EmptyBorder(10, 10, 10, 10));
JScrollPane scrollPane = new JScrollPane(lblOptionDescription);
scrollPane.setBorder(new EmptyBorder(0, 0, 0, 0));
splitPane.setRightComponent(scrollPane);
}
}
{
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
getContentPane().add(buttonPane, BorderLayout.SOUTH);
{
JButton okButton = new JButton("OK");
okButton.setActionCommand("OK");
okButton.addActionListener(this);
buttonPane.add(okButton);
getRootPane().setDefaultButton(okButton);
}
{
JButton cancelButton = new JButton("Cancel");
cancelButton.setActionCommand("Cancel");
cancelButton.addActionListener(this);
buttonPane.add(cancelButton);
}
}
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
future.complete(false);
}
@Override
public void windowClosed(WindowEvent e) {
// Just in case closing didn't get triggered - if something else called dispose() the
// future will have already completed
future.complete(false);
}
});
}
private class OptionTableModel implements TableModel {
private List<OptionTempHandler> opts = new ArrayList<OptionTempHandler>();
public OptionTableModel(List<IOptionDetails> givenOpts) {
for (IOptionDetails opt : givenOpts) {
opts.add(new OptionTempHandler(opt));
}
}
@Override
public int getRowCount() {
return opts.size();
}
@Override
public int getColumnCount() {
return 2;
}
private final String[] columnNames = {"Enabled", "Mod name"};
private final Class<?>[] columnTypes = {Boolean.class, String.class};
private final boolean[] columnEditables = {true, false};
@Override
public String getColumnName(int columnIndex) {
return columnNames[columnIndex];
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return columnTypes[columnIndex];
}
@Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnEditables[columnIndex];
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
OptionTempHandler opt = opts.get(rowIndex);
return columnIndex == 0 ? opt.getOptionValue() : opt.getName();
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (columnIndex == 0) {
OptionTempHandler opt = opts.get(rowIndex);
opt.setOptionValue((boolean) aValue);
}
}
// Noop, the table model doesn't change!
@Override
public void addTableModelListener(TableModelListener l) {}
@Override
public void removeTableModelListener(TableModelListener l) {}
public String getDescription(int rowIndex) {
return opts.get(rowIndex).getOptionDescription();
}
public void finalise() {
for (OptionTempHandler opt : opts) {
opt.finalise();
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("OK")) {
tableModel.finalise();
future.complete(true);
dispose();
} else if (e.getActionCommand().equals("Cancel")) {
future.complete(false);
dispose();
}
}
}