Separate IUserInterface logic out into GUIHandler

This commit is contained in:
comp500 2020-12-13 16:34:00 +00:00
parent f5b22f37a4
commit 0df48d19a9
3 changed files with 195 additions and 179 deletions

View File

@ -4,7 +4,7 @@ package link.infra.packwiz.installer
import link.infra.packwiz.installer.metadata.SpaceSafeURI import link.infra.packwiz.installer.metadata.SpaceSafeURI
import link.infra.packwiz.installer.ui.cli.CLIHandler import link.infra.packwiz.installer.ui.cli.CLIHandler
import link.infra.packwiz.installer.ui.gui.InstallWindow import link.infra.packwiz.installer.ui.gui.GUIHandler
import org.apache.commons.cli.DefaultParser import org.apache.commons.cli.DefaultParser
import org.apache.commons.cli.Options import org.apache.commons.cli.Options
import org.apache.commons.cli.ParseException import org.apache.commons.cli.ParseException
@ -47,7 +47,7 @@ class Main(args: Array<String>) {
guiEnabled = false guiEnabled = false
} }
val ui = if (guiEnabled) InstallWindow() else CLIHandler() val ui = if (guiEnabled) GUIHandler() else CLIHandler()
val unparsedArgs = cmd.args val unparsedArgs = cmd.args
if (unparsedArgs.size > 1) { if (unparsedArgs.size > 1) {

View File

@ -0,0 +1,134 @@
package link.infra.packwiz.installer.ui.gui
import link.infra.packwiz.installer.ui.IUserInterface
import link.infra.packwiz.installer.ui.IUserInterface.ExceptionListResult
import link.infra.packwiz.installer.ui.data.ExceptionDetails
import link.infra.packwiz.installer.ui.data.IOptionDetails
import link.infra.packwiz.installer.ui.data.InstallProgress
import java.awt.EventQueue
import java.util.concurrent.CompletableFuture
import java.util.concurrent.Future
import javax.swing.JDialog
import javax.swing.JOptionPane
import javax.swing.UIManager
import kotlin.system.exitProcess
class GUIHandler : IUserInterface {
private lateinit var frmPackwizlauncher: InstallWindow
@Volatile
override var optionsButtonPressed = false
@Volatile
override var cancelButtonPressed = false
private var title = "Updating modpack..."
init {
EventQueue.invokeAndWait {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
} catch (e: Exception) {
println("Failed to set look and feel:")
e.printStackTrace()
}
frmPackwizlauncher = InstallWindow(this).apply {
title = this@GUIHandler.title
}
}
}
override fun show() = EventQueue.invokeLater {
frmPackwizlauncher.isVisible = true
}
override fun dispose() = EventQueue.invokeAndWait {
frmPackwizlauncher.dispose()
}
override fun handleException(e: Exception) {
e.printStackTrace()
EventQueue.invokeAndWait {
JOptionPane.showMessageDialog(null,
"An error occurred: \n" + e.javaClass.canonicalName + ": " + e.message,
title, JOptionPane.ERROR_MESSAGE)
}
}
override fun handleExceptionAndExit(e: Exception) {
e.printStackTrace()
EventQueue.invokeAndWait {
JOptionPane.showMessageDialog(null,
"A fatal error occurred: \n" + e.javaClass.canonicalName + ": " + e.message,
title, JOptionPane.ERROR_MESSAGE)
exitProcess(1)
}
}
override fun setTitle(title: String) {
this.title = title
EventQueue.invokeLater { frmPackwizlauncher.title = title }
}
override fun submitProgress(progress: InstallProgress) {
val sb = StringBuilder()
if (progress.hasProgress) {
sb.append('(')
sb.append(progress.progress)
sb.append('/')
sb.append(progress.progressTotal)
sb.append(") ")
}
sb.append(progress.message)
// TODO: better logging library?
println(sb.toString())
EventQueue.invokeLater {
frmPackwizlauncher.displayProgress(progress)
}
}
override fun showOptions(options: List<IOptionDetails>): Future<Boolean> {
val future = CompletableFuture<Boolean>()
EventQueue.invokeLater {
if (options.isEmpty()) {
JOptionPane.showMessageDialog(null,
"This modpack has no optional mods!",
"Optional mods", JOptionPane.INFORMATION_MESSAGE)
future.complete(false)
} else {
OptionsSelectWindow(options, future, frmPackwizlauncher).apply {
defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE
isVisible = true
}
}
}
return future
}
override fun showExceptions(exceptions: List<ExceptionDetails>, numTotal: Int, allowsIgnore: Boolean): Future<ExceptionListResult> {
val future = CompletableFuture<ExceptionListResult>()
EventQueue.invokeLater {
ExceptionListWindow(exceptions, future, numTotal, allowsIgnore, frmPackwizlauncher).apply {
defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE
isVisible = true
}
}
return future
}
override fun disableOptionsButton() = EventQueue.invokeLater {
frmPackwizlauncher.disableOptionsButton()
}
override fun showCancellationDialog(): Future<IUserInterface.CancellationResult> {
val future = CompletableFuture<IUserInterface.CancellationResult>()
EventQueue.invokeLater {
val buttons = arrayOf("Quit", "Ignore")
val result = JOptionPane.showOptionDialog(frmPackwizlauncher,
"The installation was cancelled. Would you like to quit the game, or ignore the update and start the game?",
"Cancelled installation",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, buttons, buttons[0])
future.complete(if (result == 0) IUserInterface.CancellationResult.QUIT else IUserInterface.CancellationResult.CONTINUE)
}
return future
}
}

View File

@ -1,38 +1,21 @@
package link.infra.packwiz.installer.ui.gui package link.infra.packwiz.installer.ui.gui
import link.infra.packwiz.installer.ui.IUserInterface
import link.infra.packwiz.installer.ui.IUserInterface.ExceptionListResult
import link.infra.packwiz.installer.ui.data.ExceptionDetails
import link.infra.packwiz.installer.ui.data.IOptionDetails
import link.infra.packwiz.installer.ui.data.InstallProgress import link.infra.packwiz.installer.ui.data.InstallProgress
import java.awt.* import java.awt.BorderLayout
import java.util.concurrent.CompletableFuture import java.awt.Component
import java.util.concurrent.Future import java.awt.GridBagConstraints
import java.awt.GridBagLayout
import javax.swing.* import javax.swing.*
import javax.swing.border.EmptyBorder import javax.swing.border.EmptyBorder
import kotlin.system.exitProcess
class InstallWindow : IUserInterface { class InstallWindow(private val handler: GUIHandler) : JFrame() {
private lateinit var frmPackwizlauncher: JFrame private var lblProgresslabel: JLabel
private lateinit var lblProgresslabel: JLabel private var progressBar: JProgressBar
private lateinit var progressBar: JProgressBar private var btnOptions: JButton
private lateinit var btnOptions: JButton
@Volatile
override var optionsButtonPressed = false
@Volatile
override var cancelButtonPressed = false
private var title = "Updating modpack..."
// TODO: separate JFrame junk from IUserInterface junk?
init { init {
EventQueue.invokeAndWait {
frmPackwizlauncher = JFrame().apply {
title = this@InstallWindow.title
setBounds(100, 100, 493, 95) setBounds(100, 100, 493, 95)
defaultCloseOperation = JFrame.EXIT_ON_CLOSE defaultCloseOperation = EXIT_ON_CLOSE
setLocationRelativeTo(null) setLocationRelativeTo(null)
// Progress bar and loading text // Progress bar and loading text
@ -60,7 +43,7 @@ class InstallWindow : IUserInterface {
addActionListener { addActionListener {
text = "Loading..." text = "Loading..."
isEnabled = false isEnabled = false
optionsButtonPressed = true handler.optionsButtonPressed = true
} }
} }
add(btnOptions, GridBagConstraints().apply { add(btnOptions, GridBagConstraints().apply {
@ -71,7 +54,7 @@ class InstallWindow : IUserInterface {
add(JButton("Cancel").apply { add(JButton("Cancel").apply {
addActionListener { addActionListener {
isEnabled = false isEnabled = false
cancelButtonPressed = true handler.cancelButtonPressed = true
} }
}, GridBagConstraints().apply { }, GridBagConstraints().apply {
gridx = 0 gridx = 0
@ -79,64 +62,8 @@ class InstallWindow : IUserInterface {
}) })
}, BorderLayout.EAST) }, BorderLayout.EAST)
} }
}
}
override fun show() { fun displayProgress(progress: InstallProgress) {
EventQueue.invokeLater {
try {
// TODO: shouldn't we do this before everything else?
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
frmPackwizlauncher.isVisible = true
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun dispose() {
EventQueue.invokeAndWait {
frmPackwizlauncher.dispose()
}
}
override fun handleException(e: Exception) {
e.printStackTrace()
EventQueue.invokeAndWait {
JOptionPane.showMessageDialog(null,
"An error occurred: \n" + e.javaClass.canonicalName + ": " + e.message,
title, JOptionPane.ERROR_MESSAGE)
}
}
override fun handleExceptionAndExit(e: Exception) {
e.printStackTrace()
EventQueue.invokeAndWait {
JOptionPane.showMessageDialog(null,
"A fatal error occurred: \n" + e.javaClass.canonicalName + ": " + e.message,
title, JOptionPane.ERROR_MESSAGE)
exitProcess(1)
}
}
override fun setTitle(title: String) {
this.title = title
EventQueue.invokeLater { frmPackwizlauncher.title = title }
}
override fun submitProgress(progress: InstallProgress) {
val sb = StringBuilder()
if (progress.hasProgress) {
sb.append('(')
sb.append(progress.progress)
sb.append('/')
sb.append(progress.progressTotal)
sb.append(") ")
}
sb.append(progress.message)
// TODO: better logging library?
println(sb.toString())
EventQueue.invokeLater {
if (progress.hasProgress) { if (progress.hasProgress) {
progressBar.isIndeterminate = false progressBar.isIndeterminate = false
progressBar.value = progress.progress progressBar.value = progress.progress
@ -147,56 +74,11 @@ class InstallWindow : IUserInterface {
} }
lblProgresslabel.text = progress.message lblProgresslabel.text = progress.message
} }
}
override fun showOptions(options: List<IOptionDetails>): Future<Boolean> { fun disableOptionsButton() {
val future = CompletableFuture<Boolean>()
EventQueue.invokeLater {
if (options.isEmpty()) {
JOptionPane.showMessageDialog(null,
"This modpack has no optional mods!",
"Optional mods", JOptionPane.INFORMATION_MESSAGE)
future.complete(false)
} else {
OptionsSelectWindow(options, future, frmPackwizlauncher).apply {
defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE
isVisible = true
}
}
}
return future
}
override fun showExceptions(exceptions: List<ExceptionDetails>, numTotal: Int, allowsIgnore: Boolean): Future<ExceptionListResult> {
val future = CompletableFuture<ExceptionListResult>()
EventQueue.invokeLater {
ExceptionListWindow(exceptions, future, numTotal, allowsIgnore, frmPackwizlauncher).apply {
defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE
isVisible = true
}
}
return future
}
override fun disableOptionsButton() {
EventQueue.invokeLater {
btnOptions.apply { btnOptions.apply {
text = "No optional mods" text = "No optional mods"
isEnabled = false isEnabled = false
} }
} }
} }
override fun showCancellationDialog(): Future<IUserInterface.CancellationResult> {
val future = CompletableFuture<IUserInterface.CancellationResult>()
EventQueue.invokeLater {
val buttons = arrayOf("Quit", "Ignore")
val result = JOptionPane.showOptionDialog(frmPackwizlauncher,
"The installation was cancelled. Would you like to quit the game, or ignore the update and start the game?",
"Cancelled installation",
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, buttons, buttons[0])
future.complete(if (result == 0) IUserInterface.CancellationResult.QUIT else IUserInterface.CancellationResult.CONTINUE)
}
return future
}
}