From 0df48d19a9a197ee5d1749a1e3e23e3e188ff7d6 Mon Sep 17 00:00:00 2001 From: comp500 Date: Sun, 13 Dec 2020 16:34:00 +0000 Subject: [PATCH] Separate IUserInterface logic out into GUIHandler --- .../link/infra/packwiz/installer/Main.kt | 4 +- .../packwiz/installer/ui/gui/GUIHandler.kt | 134 ++++++++++ .../packwiz/installer/ui/gui/InstallWindow.kt | 236 +++++------------- 3 files changed, 195 insertions(+), 179 deletions(-) create mode 100644 src/main/kotlin/link/infra/packwiz/installer/ui/gui/GUIHandler.kt diff --git a/src/main/kotlin/link/infra/packwiz/installer/Main.kt b/src/main/kotlin/link/infra/packwiz/installer/Main.kt index c50dc71..72a4c10 100644 --- a/src/main/kotlin/link/infra/packwiz/installer/Main.kt +++ b/src/main/kotlin/link/infra/packwiz/installer/Main.kt @@ -4,7 +4,7 @@ package link.infra.packwiz.installer import link.infra.packwiz.installer.metadata.SpaceSafeURI 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.Options import org.apache.commons.cli.ParseException @@ -47,7 +47,7 @@ class Main(args: Array) { guiEnabled = false } - val ui = if (guiEnabled) InstallWindow() else CLIHandler() + val ui = if (guiEnabled) GUIHandler() else CLIHandler() val unparsedArgs = cmd.args if (unparsedArgs.size > 1) { diff --git a/src/main/kotlin/link/infra/packwiz/installer/ui/gui/GUIHandler.kt b/src/main/kotlin/link/infra/packwiz/installer/ui/gui/GUIHandler.kt new file mode 100644 index 0000000..042fb2b --- /dev/null +++ b/src/main/kotlin/link/infra/packwiz/installer/ui/gui/GUIHandler.kt @@ -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): Future { + val future = CompletableFuture() + 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, numTotal: Int, allowsIgnore: Boolean): Future { + val future = CompletableFuture() + 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 { + val future = CompletableFuture() + 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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/link/infra/packwiz/installer/ui/gui/InstallWindow.kt b/src/main/kotlin/link/infra/packwiz/installer/ui/gui/InstallWindow.kt index 69eddac..3558cf0 100644 --- a/src/main/kotlin/link/infra/packwiz/installer/ui/gui/InstallWindow.kt +++ b/src/main/kotlin/link/infra/packwiz/installer/ui/gui/InstallWindow.kt @@ -1,202 +1,84 @@ 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.* -import java.util.concurrent.CompletableFuture -import java.util.concurrent.Future +import java.awt.BorderLayout +import java.awt.Component +import java.awt.GridBagConstraints +import java.awt.GridBagLayout import javax.swing.* import javax.swing.border.EmptyBorder -import kotlin.system.exitProcess -class InstallWindow : IUserInterface { - private lateinit var frmPackwizlauncher: JFrame - private lateinit var lblProgresslabel: JLabel - private lateinit var progressBar: JProgressBar - 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? +class InstallWindow(private val handler: GUIHandler) : JFrame() { + private var lblProgresslabel: JLabel + private var progressBar: JProgressBar + private var btnOptions: JButton init { - EventQueue.invokeAndWait { - frmPackwizlauncher = JFrame().apply { - title = this@InstallWindow.title - setBounds(100, 100, 493, 95) - defaultCloseOperation = JFrame.EXIT_ON_CLOSE - setLocationRelativeTo(null) + setBounds(100, 100, 493, 95) + defaultCloseOperation = EXIT_ON_CLOSE + setLocationRelativeTo(null) - // Progress bar and loading text - add(JPanel().apply { - border = EmptyBorder(10, 10, 10, 10) - layout = BorderLayout(0, 0) + // Progress bar and loading text + add(JPanel().apply { + border = EmptyBorder(10, 10, 10, 10) + layout = BorderLayout(0, 0) - progressBar = JProgressBar().apply { - isIndeterminate = true - } - add(progressBar, BorderLayout.CENTER) - - lblProgresslabel = JLabel("Loading...") - add(lblProgresslabel, BorderLayout.SOUTH) - }, BorderLayout.CENTER) - - // Buttons - add(JPanel().apply { - border = EmptyBorder(0, 5, 0, 5) - layout = GridBagLayout() - - btnOptions = JButton("Optional mods...").apply { - alignmentX = Component.CENTER_ALIGNMENT - - addActionListener { - text = "Loading..." - isEnabled = false - optionsButtonPressed = true - } - } - add(btnOptions, GridBagConstraints().apply { - gridx = 0 - gridy = 0 - }) - - add(JButton("Cancel").apply { - addActionListener { - isEnabled = false - cancelButtonPressed = true - } - }, GridBagConstraints().apply { - gridx = 0 - gridy = 1 - }) - }, BorderLayout.EAST) + progressBar = JProgressBar().apply { + isIndeterminate = true } - } - } + add(progressBar, BorderLayout.CENTER) - override fun show() { - EventQueue.invokeLater { - try { - // TODO: shouldn't we do this before everything else? - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()) - frmPackwizlauncher.isVisible = true - } catch (e: Exception) { - e.printStackTrace() - } - } - } + lblProgresslabel = JLabel("Loading...") + add(lblProgresslabel, BorderLayout.SOUTH) + }, BorderLayout.CENTER) - override fun dispose() { - EventQueue.invokeAndWait { - frmPackwizlauncher.dispose() - } - } + // Buttons + add(JPanel().apply { + border = EmptyBorder(0, 5, 0, 5) + layout = GridBagLayout() - 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) - } - } + btnOptions = JButton("Optional mods...").apply { + alignmentX = Component.CENTER_ALIGNMENT - 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) { - progressBar.isIndeterminate = false - progressBar.value = progress.progress - progressBar.maximum = progress.progressTotal - } else { - progressBar.isIndeterminate = true - progressBar.value = 0 - } - lblProgresslabel.text = progress.message - } - } - - override fun showOptions(options: List): Future { - val future = CompletableFuture() - 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 + addActionListener { + text = "Loading..." + isEnabled = false + handler.optionsButtonPressed = true } } - } - return future + add(btnOptions, GridBagConstraints().apply { + gridx = 0 + gridy = 0 + }) + + add(JButton("Cancel").apply { + addActionListener { + isEnabled = false + handler.cancelButtonPressed = true + } + }, GridBagConstraints().apply { + gridx = 0 + gridy = 1 + }) + }, BorderLayout.EAST) } - override fun showExceptions(exceptions: List, numTotal: Int, allowsIgnore: Boolean): Future { - val future = CompletableFuture() - EventQueue.invokeLater { - ExceptionListWindow(exceptions, future, numTotal, allowsIgnore, frmPackwizlauncher).apply { - defaultCloseOperation = JDialog.DISPOSE_ON_CLOSE - isVisible = true - } + fun displayProgress(progress: InstallProgress) { + if (progress.hasProgress) { + progressBar.isIndeterminate = false + progressBar.value = progress.progress + progressBar.maximum = progress.progressTotal + } else { + progressBar.isIndeterminate = true + progressBar.value = 0 } - return future + lblProgresslabel.text = progress.message } - override fun disableOptionsButton() { - EventQueue.invokeLater { - btnOptions.apply { - text = "No optional mods" - isEnabled = false - } + fun disableOptionsButton() { + btnOptions.apply { + text = "No optional mods" + isEnabled = false } } - - override fun showCancellationDialog(): Future { - val future = CompletableFuture() - 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 - } } \ No newline at end of file