223 lines
9.0 KiB
Kotlin
223 lines
9.0 KiB
Kotlin
package io.gitlab.jfronny.inceptum.gtk
|
|
|
|
import io.gitlab.jfronny.commons.OSUtils
|
|
import io.gitlab.jfronny.commons.io.JFiles
|
|
import io.gitlab.jfronny.inceptum.common.MetaHolder
|
|
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder
|
|
import io.gitlab.jfronny.inceptum.gtk.util.I18n
|
|
import io.gitlab.jfronny.inceptum.gtk.util.Log
|
|
import io.gitlab.jfronny.inceptum.gtk.window.AboutWindow
|
|
import io.gitlab.jfronny.inceptum.gtk.window.create.NewInstanceWindow
|
|
import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog
|
|
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog
|
|
import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow
|
|
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv
|
|
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager
|
|
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount
|
|
import io.gitlab.jfronny.inceptum.launcher.system.importer.Importers
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList
|
|
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher
|
|
import io.gitlab.jfronny.inceptum.launcher.system.launch.LaunchType
|
|
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps
|
|
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
|
|
import org.gnome.gio.Cancellable
|
|
import org.gnome.gtk.*
|
|
import java.awt.Toolkit
|
|
import java.awt.datatransfer.DataFlavor
|
|
import java.io.IOException
|
|
import java.nio.file.Path
|
|
|
|
object GtkMenubar {
|
|
@JvmField
|
|
var newMenu: MenuBuilder? = null
|
|
@JvmField
|
|
var accountsMenu: MenuBuilder? = null
|
|
@JvmField
|
|
var launchMenu: MenuBuilder? = null
|
|
|
|
@JvmStatic
|
|
fun create(app: Application) {
|
|
val menu = MenuBuilder(app)
|
|
val file = menu.submenu("file")
|
|
newMenu = file.submenu("new")
|
|
generateNewMenu(app)
|
|
file.button("redownload") {
|
|
val state = ProcessState(3 + Steps.STEPS.size * InstanceList.size(), "Initializing")
|
|
ProcessStateWatcherDialog.show(
|
|
GtkEnvBackend.dialogParent,
|
|
"Reloading data",
|
|
"Could not execute refresh task",
|
|
state
|
|
) {
|
|
state.incrementStep("Clearing cache directories")
|
|
JFiles.clearDirectory(MetaHolder.ASSETS_DIR)
|
|
JFiles.clearDirectory(MetaHolder.LIBRARIES_DIR) { path: Path -> !path.startsWith(MetaHolder.LIBRARIES_DIR.resolve("io/gitlab/jfronny")) }
|
|
JFiles.clearDirectory(MetaHolder.NATIVES_DIR) { path: Path -> !path.startsWith(MetaHolder.NATIVES_DIR.resolve("forceload")) }
|
|
JFiles.clearDirectory(MetaHolder.CACHE_DIR)
|
|
if (state.isCancelled) return@show
|
|
state.incrementStep("Reloading instance list")
|
|
InstanceList.reset()
|
|
InstanceList.forEach<IOException> { instance: Instance? ->
|
|
if (state.isCancelled) return@forEach
|
|
Steps.reDownload(instance, state)
|
|
}
|
|
}
|
|
}
|
|
file.button("exit") { app.quit() }
|
|
launchMenu = menu.submenu("launch")
|
|
generateLaunchMenu(app)
|
|
accountsMenu = menu.submenu("account")
|
|
generateAccountsMenu(app)
|
|
val help = menu.submenu("help")
|
|
help.button("about") { AboutWindow.createAndShow() }
|
|
help.button("log") {
|
|
//TODO
|
|
}
|
|
}
|
|
|
|
@JvmStatic
|
|
fun generateNewMenu(app: Application) {
|
|
newMenu!!.clear()
|
|
newMenu!!.button("new") { NewInstanceWindow(app).show() }
|
|
newMenu!!.button("file") {
|
|
val dialog = FileChooserNative(
|
|
I18n["menu.file.new.file"],
|
|
GtkEnvBackend.dialogParent,
|
|
FileChooserAction.OPEN,
|
|
"_" + I18n["select"],
|
|
"_" + I18n["cancel"]
|
|
)
|
|
val filter = FileFilter()
|
|
filter.addPattern("*.zip")
|
|
filter.addPattern("*.mrpack")
|
|
dialog.addFilter(filter)
|
|
dialog.onResponse { responseId: Int ->
|
|
if (responseId == ResponseType.ACCEPT.value) {
|
|
val file = dialog.file!!.path
|
|
if (file == null) {
|
|
LauncherEnv.showError("The path returned by the file dialog is null", "Could not import")
|
|
return@onResponse
|
|
}
|
|
val state = ProcessState(Importers.MAX_STEPS, "Initializing")
|
|
ProcessStateWatcherDialog.show(
|
|
GtkEnvBackend.dialogParent,
|
|
I18n["menu.file.new.file"],
|
|
I18n["menu.file.new.file.error"],
|
|
state
|
|
) {
|
|
Importers.importPack(Path.of(file), state)
|
|
}
|
|
}
|
|
}
|
|
dialog.show()
|
|
}
|
|
newMenu!!.button("url") {
|
|
readClipboard { clipboard ->
|
|
LauncherEnv.getInput(
|
|
I18n["menu.file.new.url"],
|
|
I18n["menu.file.new.url.details"],
|
|
clipboard ?: "",
|
|
{ s: String? ->
|
|
val state = ProcessState(Importers.MAX_STEPS, "Initializing")
|
|
ProcessStateWatcherDialog.show(
|
|
GtkEnvBackend.dialogParent,
|
|
I18n["menu.file.new.url"],
|
|
I18n["menu.file.new.url.error"],
|
|
state
|
|
) {
|
|
Importers.importPack(s, state)
|
|
}
|
|
}, {})
|
|
}
|
|
}
|
|
}
|
|
|
|
private fun readClipboard(continuation: (String?) -> Unit) {
|
|
if (OSUtils.TYPE == OSUtils.Type.LINUX) {
|
|
val clipboard = GtkEnvBackend.dialogParent!!.display.clipboard
|
|
clipboard.readTextAsync(Cancellable()) { _, res, _ ->
|
|
continuation(clipboard.readTextFinish(res))
|
|
}
|
|
} else {
|
|
continuation(Toolkit.getDefaultToolkit().systemClipboard.getData(DataFlavor.stringFlavor) as String?)
|
|
}
|
|
}
|
|
|
|
@JvmStatic
|
|
fun generateLaunchMenu(app: Application) {
|
|
launchMenu!!.clear()
|
|
try {
|
|
InstanceList.forEach<RuntimeException> { entry: Instance ->
|
|
launchMenu!!.literalButton(entry.id + ".launch", entry.toString()) {
|
|
launch(entry, LaunchType.Client)
|
|
}
|
|
}
|
|
} catch (e: IOException) {
|
|
Log.error("Could not generate launch menu", e)
|
|
}
|
|
}
|
|
|
|
@JvmStatic
|
|
fun launch(instance: Instance, launchType: LaunchType) {
|
|
if (instance.isSetupLocked) {
|
|
LauncherEnv.showError(I18n["instance.launch.locked.setup"], I18n["instance.launch.locked"])
|
|
} else if (instance.isRunningLocked) {
|
|
LauncherEnv.showOkCancel(
|
|
I18n["instance.launch.locked.running"],
|
|
I18n["instance.launch.locked"]
|
|
) { forceLaunch(instance, launchType) }
|
|
} else forceLaunch(instance, launchType)
|
|
}
|
|
|
|
private fun forceLaunch(instance: Instance, launchType: LaunchType) {
|
|
val state = Steps.createProcessState()
|
|
ProcessStateWatcherDialog.show(
|
|
GtkEnvBackend.dialogParent,
|
|
I18n["instance.launch.title"],
|
|
I18n["instance.launch.error"],
|
|
state
|
|
) {
|
|
try {
|
|
Steps.reDownload(instance, state)
|
|
} catch (e: IOException) {
|
|
Log.error("Could not fetch instance, trying to start anyways", e)
|
|
}
|
|
if (state.isCancelled) return@show
|
|
state.updateStep("Starting Game")
|
|
try {
|
|
if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance)
|
|
else InstanceLauncher.launch(
|
|
instance,
|
|
launchType,
|
|
false,
|
|
AccountManager.NULL_AUTH
|
|
)
|
|
} catch (e: Throwable) {
|
|
LauncherEnv.showError("Could not start instance", e)
|
|
}
|
|
}
|
|
}
|
|
|
|
@JvmStatic
|
|
fun generateAccountsMenu(app: Application) {
|
|
accountsMenu!!.clear()
|
|
accountsMenu!!.button("new") { MicrosoftLoginDialog(GtkEnvBackend.dialogParent).show() }
|
|
accountsMenu!!.button("manage") {
|
|
val window = LauncherSettingsWindow(app)
|
|
window.activePage = "settings.accounts"
|
|
window.show()
|
|
}
|
|
val accounts: MutableList<MicrosoftAccount?> = ArrayList(AccountManager.getAccounts())
|
|
accounts.add(null)
|
|
accountsMenu!!.literalRadio(
|
|
"account",
|
|
accounts[AccountManager.getSelectedIndex()],
|
|
accounts,
|
|
{ _, acc: MicrosoftAccount? ->
|
|
if (acc == null) return@literalRadio I18n["account.none"]
|
|
acc.minecraftUsername
|
|
}) { account: MicrosoftAccount? -> AccountManager.switchAccount(account) }
|
|
}
|
|
}
|