Implement new instance window, bump java and GTK

This commit is contained in:
Johannes Frohnmeyer 2023-06-30 14:02:31 +02:00
parent e9f8af5617
commit 1be0d68a56
Signed by: Johannes
GPG Key ID: E76429612C2929F4
21 changed files with 386 additions and 126 deletions

View File

@ -17,10 +17,7 @@ val jbAnnotationsVersion by extra("24.0.1")
val lwjglVersion by extra("3.3.2") val lwjglVersion by extra("3.3.2")
val imguiVersion by extra("1.86.10") val imguiVersion by extra("1.86.10")
// launcher-gtk // launcher-gtk
val javagiVersion by extra("0.4") val javagiVersion by extra("v0.5.1")
val glibVersion by extra("1.2.10")
val gtkVersion by extra("4.8.3")
val adwaitaVersion by extra("1.2.0")
val flavorProp: String by extra(prop("flavor", "custom")) val flavorProp: String by extra(prop("flavor", "custom"))
if (!setOf("custom", "maven", "fat", "windows", "linux", "macos").contains(flavorProp)) throw IllegalStateException("Unsupported flavor: $flavorProp") if (!setOf("custom", "maven", "fat", "windows", "linux", "macos").contains(flavorProp)) throw IllegalStateException("Unsupported flavor: $flavorProp")

View File

@ -10,5 +10,5 @@ repositories {
dependencies { dependencies {
implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2") implementation("gradle.plugin.com.github.johnrengelman:shadow:7.1.2")
implementation("de.undercouch:gradle-download-task:5.1.2") implementation("de.undercouch:gradle-download-task:5.1.2")
implementation("io.gitlab.jfronny:convention:1.3-SNAPSHOT") implementation("io.gitlab.jfronny:convention:1.4-SNAPSHOT")
} }

View File

@ -3,6 +3,12 @@ plugins {
`maven-publish` `maven-publish`
} }
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(20))
}
}
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://maven.frohnmeyer-wds.de/artifacts") maven("https://maven.frohnmeyer-wds.de/artifacts")

View File

@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
id("inceptum.application") id("inceptum.application")
id("com.github.johnrengelman.shadow") id("com.github.johnrengelman.shadow")
kotlin("jvm") version "1.8.21" kotlin("jvm") version "1.9.0-RC"
} }
application { application {
@ -12,18 +12,19 @@ application {
repositories { repositories {
mavenLocal() mavenLocal()
maven { url = uri("https://maven.frohnmeyer-wds.de/java-gi") } maven("https://jitpack.io") {
content {
includeGroup("com.github.jwharm.java-gi")
}
}
} }
dependencies { dependencies {
val javagiVersion: String by rootProject.extra val javagiVersion: String by rootProject.extra
val glibVersion: String by rootProject.extra
val gtkVersion: String by rootProject.extra
val adwaitaVersion: String by rootProject.extra
implementation("io.github.jwharm.javagi:glib:$glibVersion-$javagiVersion") implementation("com.github.jwharm.java-gi:glib:$javagiVersion")
implementation("io.github.jwharm.javagi:gtk:$gtkVersion-$javagiVersion") implementation("com.github.jwharm.java-gi:gtk:$javagiVersion")
implementation("io.github.jwharm.javagi:adwaita:$adwaitaVersion-$javagiVersion") implementation("com.github.jwharm.java-gi:adwaita:$javagiVersion")
implementation(project(":launcher")) implementation(project(":launcher"))
} }
@ -51,13 +52,4 @@ tasks.runShadow {
jvmArgs("--enable-preview", "--enable-native-access=ALL-UNNAMED") jvmArgs("--enable-preview", "--enable-native-access=ALL-UNNAMED")
} }
kotlin {
sourceSets.all {
languageSettings {
languageVersion = "2.0"
progressiveMode = true
}
}
}
tasks.withType(KotlinCompile::class) { compilerOptions.freeCompilerArgs.addAll("-Xlambdas=indy") } tasks.withType(KotlinCompile::class) { compilerOptions.freeCompilerArgs.addAll("-Xlambdas=indy") }

View File

@ -2,11 +2,11 @@ package io.gitlab.jfronny.inceptum.gtk
import io.gitlab.jfronny.commons.StringFormatter import io.gitlab.jfronny.commons.StringFormatter
import io.gitlab.jfronny.inceptum.common.Utils import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.util.markup
import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog
import io.gitlab.jfronny.inceptum.gtk.window.dialog.StringInputDialog import io.gitlab.jfronny.inceptum.gtk.window.dialog.StringInputDialog
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv.EnvBackend import io.gitlab.jfronny.inceptum.launcher.LauncherEnv.EnvBackend
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount
import org.gnome.gio.Cancellable
import org.gnome.gtk.* import org.gnome.gtk.*
import java.util.function.Consumer import java.util.function.Consumer
@ -16,21 +16,21 @@ object GtkEnvBackend : EnvBackend {
override fun showError(message: String, title: String) { override fun showError(message: String, title: String) {
Utils.LOGGER.error(message) Utils.LOGGER.error(message)
simpleDialog(message, title, MessageType.ERROR, ButtonsType.CLOSE, null, null) simpleDialog(message, title, null, null)
} }
override fun showError(message: String, t: Throwable) { override fun showError(message: String, t: Throwable) {
simpleDialog(StringFormatter.toString(t), message, MessageType.ERROR, ButtonsType.CLOSE, null, null) simpleDialog(StringFormatter.toString(t), message, null, null)
} }
override fun showInfo(message: String, title: String) { override fun showInfo(message: String, title: String) {
Utils.LOGGER.info(message) Utils.LOGGER.info(message)
simpleDialog(message, title, MessageType.INFO, ButtonsType.CLOSE, null, null) simpleDialog(message, title, null, null)
} }
override fun showOkCancel(message: String, title: String, ok: Runnable, cancel: Runnable, defaultCancel: Boolean) { override fun showOkCancel(message: String, title: String, ok: Runnable, cancel: Runnable, defaultCancel: Boolean) {
Utils.LOGGER.info(message) Utils.LOGGER.info(message)
simpleDialog(message, title, MessageType.QUESTION, ButtonsType.OK_CANCEL, ok, cancel) simpleDialog(message, title, ok, cancel)
} }
override fun getInput( override fun getInput(
@ -52,37 +52,40 @@ object GtkEnvBackend : EnvBackend {
) )
dialog.title = prompt dialog.title = prompt
dialog.onResponse(processResponses(dialog, { ok.accept(dialog.input) }, cancel)) dialog.onResponse(processResponses(dialog, { ok.accept(dialog.input) }, cancel))
dialog.show() dialog.visible = true
} }
override fun showLoginRefreshPrompt(account: MicrosoftAccount) = override fun showLoginRefreshPrompt(account: MicrosoftAccount) =
schedule { MicrosoftLoginDialog(dialogParent, account).show() } schedule { MicrosoftLoginDialog(dialogParent, account).visible = true }
private fun simpleDialog( private fun simpleDialog(
markup: String, markup: String,
title: String, title: String,
type: MessageType,
buttons: ButtonsType,
ok: Runnable?, ok: Runnable?,
cancel: Runnable? cancel: Runnable?
) = schedule { simpleDialog(dialogParent, markup, title, type, buttons, ok, cancel) } ) = schedule { simpleDialog(dialogParent, markup, title, ok, cancel) }
@JvmStatic @JvmStatic
fun simpleDialog( fun simpleDialog(
parent: Window?, parent: Window?,
markup: String, markup: String,
title: String, title: String,
type: MessageType?,
buttons: ButtonsType?,
ok: Runnable?, ok: Runnable?,
cancel: Runnable? cancel: Runnable?
) { ) {
val dialog = run {
MessageDialog(parent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), type, buttons, null) val dialog = AlertDialog("")
dialog.title = title dialog.message = title
dialog.markup = markup dialog.detail = markup
dialog.onResponse(processResponses(dialog, ok, cancel)) dialog.modal = true
dialog.show() dialog.choose(parent, Cancellable()) { _, res, _ ->
val result = dialog.chooseFinish(res)
val cancelIdx = dialog.cancelButton
val defaultIdx = dialog.defaultButton
if (result == cancelIdx) cancel?.run()
if (result == defaultIdx) ok?.run()
}
}
} }
private fun processResponses(dialog: Dialog, ok: Runnable?, cancel: Runnable?): Dialog.Response { private fun processResponses(dialog: Dialog, ok: Runnable?, cancel: Runnable?): Dialog.Response {

View File

@ -1,12 +1,13 @@
package io.gitlab.jfronny.inceptum.gtk package io.gitlab.jfronny.inceptum.gtk
import io.gitlab.jfronny.commons.OSUtils
import io.gitlab.jfronny.commons.io.JFiles import io.gitlab.jfronny.commons.io.JFiles
import io.gitlab.jfronny.inceptum.common.MetaHolder import io.gitlab.jfronny.inceptum.common.MetaHolder
import io.gitlab.jfronny.inceptum.common.Utils import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder
import io.gitlab.jfronny.inceptum.gtk.util.I18n import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.window.AboutWindow import io.gitlab.jfronny.inceptum.gtk.window.AboutWindow
import io.gitlab.jfronny.inceptum.gtk.window.NewInstanceWindow 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.MicrosoftLoginDialog
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog
import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow
@ -20,6 +21,8 @@ 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.launch.LaunchType
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
import org.gnome.gdk.Clipboard
import org.gnome.gio.Cancellable
import org.gnome.gtk.* import org.gnome.gtk.*
import java.awt.Toolkit import java.awt.Toolkit
import java.awt.datatransfer.DataFlavor import java.awt.datatransfer.DataFlavor
@ -111,21 +114,34 @@ object GtkMenubar {
dialog.show() dialog.show()
} }
newMenu!!.button("url") { newMenu!!.button("url") {
LauncherEnv.getInput( readClipboard { clipboard ->
I18n["menu.file.new.url"], LauncherEnv.getInput(
I18n["menu.file.new.url.details"], I18n["menu.file.new.url"],
Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor) as String, I18n["menu.file.new.url.details"],
{ s: String? -> clipboard ?: "",
val state = ProcessState(Importers.MAX_STEPS, "Initializing") { s: String? ->
ProcessStateWatcherDialog.show( val state = ProcessState(Importers.MAX_STEPS, "Initializing")
GtkEnvBackend.dialogParent, ProcessStateWatcherDialog.show(
I18n["menu.file.new.url"], GtkEnvBackend.dialogParent,
I18n["menu.file.new.url.error"], I18n["menu.file.new.url"],
state I18n["menu.file.new.url.error"],
) { state
Importers.importPack(s, 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?)
} }
} }

View File

@ -26,7 +26,10 @@ class ILabel(str: @PropertyKey(resourceBundle = I18n.BUNDLE) String, mode: Mode,
val provider = CssProvider() val provider = CssProvider()
try { try {
GtkMain::class.java.classLoader.getResourceAsStream("inceptum.css")!! GtkMain::class.java.classLoader.getResourceAsStream("inceptum.css")!!
.use { provider.loadFromData(it.readAllBytes()) } .use {
val bytes = it.readAllBytes()
provider.loadFromData(String(bytes), bytes.size.toLong())
}
} catch (t: Throwable) { } catch (t: Throwable) {
throw RuntimeException(t) throw RuntimeException(t)
} }

View File

@ -4,10 +4,10 @@ import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance
import org.gnome.gtk.Image import org.gnome.gtk.Image
import org.gnome.gtk.Spinner import org.gnome.gtk.Spinner
import org.gnome.gtk.Stack import org.gnome.gtk.Stack
import java.lang.foreign.Addressable import java.lang.foreign.MemorySegment
class InstanceThumbnail : Stack { class InstanceThumbnail : Stack {
private constructor(address: Addressable) : super(address) private constructor(address: MemorySegment) : super(address)
constructor() : super() { constructor() : super() {
val spinner = Spinner() val spinner = Spinner()

View File

@ -0,0 +1,32 @@
package io.gitlab.jfronny.inceptum.gtk.control
import org.gnome.gtk.DropDown
import org.gnome.gtk.PropertyExpression
import org.gnome.gtk.StringList
import org.gnome.gtk.StringObject
import java.util.ArrayList
import java.util.function.IntConsumer
class KDropDown<T>(options: Array<T>, private val stringify: (T) -> String, selected: Int): DropDown(options.toModel(stringify), null) {
private val onChange = ArrayList<IntConsumer>()
init {
this.selected = selected
onNotify("selected") { _ -> onChange.forEach { it.accept(this.selected) } }
expression = PropertyExpression(StringObject.getType(), null, "string")
}
fun onChange(changed: IntConsumer) {
onChange.add(changed)
}
fun updateOptions(newOptions: Array<T>, newSelected: Int) {
selected = 0
model = newOptions.toModel(stringify)
selected = newSelected
}
companion object {
private fun <T> Array<T>.toModel(stringify: (T) -> String) = StringList(map(stringify).toTypedArray())
}
}

View File

@ -0,0 +1,17 @@
package io.gitlab.jfronny.inceptum.gtk.control
import org.gnome.gtk.Entry
import java.util.function.Consumer
class KEntry(value: String? = ""): Entry() {
private val onChange = ArrayList<Consumer<String>>()
init {
text = value ?: ""
onChanged { onChange.forEach { it.accept(text) } }
}
fun onChange(changed: Consumer<String>) {
onChange.add(changed)
}
}

View File

@ -0,0 +1,15 @@
package io.gitlab.jfronny.inceptum.gtk.control.assistant
import org.gnome.gtk.AssistantPageType
import org.gnome.gtk.Box
import org.gnome.gtk.Orientation
class AssistantPage(val title: String, val type: AssistantPageType): Box(Orientation.VERTICAL, 8) {
lateinit var setComplete: (Boolean) -> Unit
private val onOpen = ArrayList<Runnable>()
fun onOpen(action: Runnable) {
onOpen.add(action)
}
fun emitOpen() = onOpen.forEach { it.run() }
}

View File

@ -0,0 +1,33 @@
package io.gitlab.jfronny.inceptum.gtk.control.assistant
import io.gitlab.jfronny.inceptum.common.Utils
import org.gnome.gtk.Application
import org.gnome.gtk.Assistant
import org.gnome.gtk.AssistantPageType
open class KAssistant(app: Application) : Assistant() {
private val pages = ArrayList<AssistantPage>()
init {
application = app
onPrepare { next ->
val page = pages.firstOrNull { it.handle() == next.handle() }
if (page == null) {
Utils.LOGGER.error("Unknown page opened in assistant")
} else {
page.emitOpen()
}
}
}
fun page(title: String, type: AssistantPageType, setup: AssistantPage.() -> Unit): Int {
val page = AssistantPage(title, type)
val idx = appendPage(page)
pages.add(page)
page.setComplete = { setPageComplete(page, it) }
page.setup()
setPageType(page, page.type)
setPageTitle(page, page.title)
return idx
}
}

View File

@ -1,6 +1,8 @@
package io.gitlab.jfronny.inceptum.gtk.control.settings package io.gitlab.jfronny.inceptum.gtk.control.settings
import io.gitlab.jfronny.inceptum.gtk.control.ILabel import io.gitlab.jfronny.inceptum.gtk.control.ILabel
import io.gitlab.jfronny.inceptum.gtk.control.KDropDown
import io.gitlab.jfronny.inceptum.gtk.control.KEntry
import io.gitlab.jfronny.inceptum.gtk.util.I18n import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.margin import io.gitlab.jfronny.inceptum.gtk.util.margin
import org.gnome.gtk.* import org.gnome.gtk.*
@ -41,12 +43,10 @@ class IRow(
} }
} }
fun setDropdown(options: Array<String>, defaultIndex: Int, changed: IntConsumer): DropDown { fun setDropdown(options: Array<String>, defaultIndex: Int, changed: IntConsumer): KDropDown<String> {
return DropDown(StringList(options), null).apply { return KDropDown(options, { it } , defaultIndex).apply {
onChange(changed)
packSmallEnd() packSmallEnd()
selected = defaultIndex
onNotify("selected") { _ -> changed.accept(selected) }
expression = PropertyExpression(StringObject.getType(), null, "string")
} }
} }
@ -69,13 +69,12 @@ class IRow(
} }
} }
fun setEntry(value: String?, changed: Consumer<String>): Entry { fun setEntry(value: String?, changed: Consumer<String>): KEntry {
return Entry().apply { return KEntry(value).apply {
text = value ?: ""
hexpand = true hexpand = true
valign = Align.CENTER valign = Align.CENTER
halign = Align.FILL halign = Align.FILL
onChanged { changed.accept(text) } onChange(changed)
append(this) append(this)
} }
} }

View File

@ -81,8 +81,6 @@ open class SettingsTab(window: Window?) : Box(Orientation.VERTICAL, 8) {
window, window,
StringFormatter.toString(t), StringFormatter.toString(t),
message, message,
MessageType.ERROR,
ButtonsType.CLOSE,
null, null,
null null
) )

View File

@ -1,15 +0,0 @@
package io.gitlab.jfronny.inceptum.gtk.window
import org.gnome.gtk.*
class NewInstanceWindow(app: Application) : Assistant() {
init {
application = app
run {
val initialPage = Box(Orientation.VERTICAL, 8)
initialPage.append(Label("Importing instances via this assistant is not yet supported, use the ImGUI"))
appendPage(initialPage)
setPageType(initialPage, AssistantPageType.INTRO)
}
}
}

View File

@ -0,0 +1,179 @@
package io.gitlab.jfronny.inceptum.gtk.window.create
import io.gitlab.jfronny.commons.StringFormatter
import io.gitlab.jfronny.commons.io.JFiles
import io.gitlab.jfronny.inceptum.common.InceptumConfig
import io.gitlab.jfronny.inceptum.common.MetaHolder
import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.control.KDropDown
import io.gitlab.jfronny.inceptum.gtk.control.KEntry
import io.gitlab.jfronny.inceptum.gtk.control.assistant.KAssistant
import io.gitlab.jfronny.inceptum.gtk.schedule
import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi
import io.gitlab.jfronny.inceptum.launcher.api.McApi
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricVersionLoaderInfo
import io.gitlab.jfronny.inceptum.launcher.model.mojang.VersionsListInfo
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceNameTool
import io.gitlab.jfronny.inceptum.launcher.system.instance.LoaderInfo
import io.gitlab.jfronny.inceptum.launcher.system.setup.SetupStepInfo
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps
import org.gnome.glib.GLib
import org.gnome.gtk.*
import java.io.IOException
class NewInstanceWindow(app: Application) : KAssistant(app) {
companion object {
private val VERSIONS = McApi.getVersions()
}
init {
var gameVersion: VersionsListInfo? = null
var useFabric = false
var fabricVersion: FabricVersionLoaderInfo? = null
var name = "New Instance"
var failureMessage = "Unknown error, please look at the log!"
var isFailure = false
page("Welcome", AssistantPageType.INTRO) {
append(Label("This assistant will guide you through the process of setting up a Minecraft instance.\nTo begin, please choose the game version you want to use"))
val versions = VERSIONS.versions.stream()
.filter { InceptumConfig.snapshots || it.type == "release" }
.toTypedArray()
val def = versions.withIndex().firstOrNull { it.value.id == VERSIONS.latest.release }?.index ?: 0
gameVersion = versions[def]
append(KDropDown(versions, { it.id }, def).apply {
onChange { gameVersion = versions[it] }
})
setComplete(true)
}
page("Loader", AssistantPageType.CONTENT) {
append(Label("Select a mod loader if you want to use mods in this instance. This can be changed later."))
var lastGameVersion: VersionsListInfo? = null
var versions = arrayOf<FabricVersionLoaderInfo>()
var def = 0
val none = CheckButton.newWithLabel("None")
val fabric = CheckButton.newWithLabel("Fabric")
none.onActivate { useFabric = false }
none.onActivate { useFabric = true }
append(none)
val fabricVersionDropdown = KDropDown(versions, { it.loader.version }, def)
fabricVersionDropdown.onChange { fabricVersion = versions[it] }
append(Box(Orientation.HORIZONTAL, 8).apply {
append(fabric)
append(fabricVersionDropdown)
})
onOpen {
if (lastGameVersion == null || lastGameVersion != gameVersion) {
versions = FabricMetaApi.getLoaderVersions(gameVersion!!).toTypedArray()
def = versions.withIndex().firstOrNull { it.value.loader.stable }?.index ?: 0
fabricVersionDropdown.updateOptions(versions, def)
lastGameVersion = gameVersion
none.active = true
fabric.active = false
useFabric = false
}
if (versions.isEmpty()) {
none.active = true
fabric.active = false
useFabric = false
fabric.sensitive = false
}
}
setComplete(true)
}
page("Name", AssistantPageType.CONTENT) {
append(Label(I18n["instance.settings.general.name.placeholder"]))
val entry = KEntry(name)
entry.placeholderText = I18n["instance.settings.general.name.placeholder"]
entry.valign
entry.onChange { name = InstanceNameTool.getNextValid(it) }
append(entry)
onOpen {
name = InstanceNameTool.getDefaultName(gameVersion!!.id, useFabric)
entry.text = name
}
setComplete(true)
}
page("Creating", AssistantPageType.PROGRESS) {
append(Label("Creating Instance"))
val progress = ProgressBar()
append(progress)
val stage = Label("")
append(stage)
onOpen {
commit()
val pState = Steps.createProcessState()
val state = SetupStepInfo(
McApi.getVersionInfo(gameVersion),
if (useFabric) LoaderInfo(fabricVersion!!.loader) else LoaderInfo.NONE,
name,
pState
)
var finished = false
var cachedState: ProcessStateWatcherDialog.State? = null
addTickCallback { widget, _ ->
if (finished) return@addTickCallback GLib.SOURCE_REMOVE
val nc = ProcessStateWatcherDialog.State(pState)
if (nc != cachedState) {
cachedState = nc
stage.setMarkup(cachedState!!.msg)
progress.fraction = cachedState!!.progress.coerceAtMost(1f).toDouble()
widget.queueDraw()
}
GLib.SOURCE_CONTINUE
}
onClose { pState.cancel() }
onCancel { pState.cancel() }
pState.updateStep("Starting install process")
Thread {
try {
for (step in Steps.STEPS) {
if (state.isCancelled) {
try {
JFiles.deleteRecursive(MetaHolder.INSTANCE_DIR.resolve(state.name))
} catch (e: IOException) {
Utils.LOGGER.error("Could not delete instance dir", e)
}
return@Thread
}
pState.incrementStep(step.name)
step.execute(state)
}
} catch (e: Throwable) {
pState.cancel()
Utils.LOGGER.error("Could not create instance")
failureMessage = StringFormatter.toString(e)
isFailure = true
} finally {
finished = true
schedule { setComplete(true) }
schedule { nextPage() }
}
}.start()
}
}
page("Done", AssistantPageType.SUMMARY) {
val status = Label("")
onOpen {
if (isFailure) {
status.setMarkup("Something went wrong while creating the instance.\n\n$failureMessage")
} else {
status.setMarkup("The instance was successfully created. You can now launch it using the main menu")
}
}
}
}
}

View File

@ -51,9 +51,7 @@ class ProcessStateWatcherDialog(
(messageArea as Box).append(progress) (messageArea as Box).append(progress)
addTickCallback { widget, _ -> addTickCallback { widget, _ ->
if (finished) return@addTickCallback GLib.SOURCE_REMOVE if (finished) return@addTickCallback GLib.SOURCE_REMOVE
val nc = State( val nc = State(state)
state
)
if (nc != cachedState) { if (nc != cachedState) {
cachedState = nc cachedState = nc
setMarkup(cachedState!!.msg) setMarkup(cachedState!!.msg)
@ -72,8 +70,6 @@ class ProcessStateWatcherDialog(
parent, parent,
StringFormatter.toString(e), StringFormatter.toString(e),
errorMessage, errorMessage,
MessageType.ERROR,
ButtonsType.CLOSE,
null, null,
null null
) )
@ -85,7 +81,7 @@ class ProcessStateWatcherDialog(
} }
@JvmRecord @JvmRecord
internal data class State(val msg: String, val progress: Float) { data class State(val msg: String, val progress: Float) {
constructor(source: ProcessState) : this(source.currentStep, source.progress) constructor(source: ProcessState) : this(source.currentStep, source.progress)
} }

View File

@ -1,7 +1,6 @@
package io.gitlab.jfronny.inceptum.gtk.window.settings.instance package io.gitlab.jfronny.inceptum.gtk.window.settings.instance
import io.gitlab.jfronny.inceptum.common.Utils import io.gitlab.jfronny.inceptum.common.Utils
import io.gitlab.jfronny.inceptum.gtk.GtkEnvBackend
import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab import io.gitlab.jfronny.inceptum.gtk.control.settings.SettingsTab
import io.gitlab.jfronny.inceptum.gtk.schedule import io.gitlab.jfronny.inceptum.gtk.schedule
import io.gitlab.jfronny.inceptum.gtk.util.I18n import io.gitlab.jfronny.inceptum.gtk.util.I18n
@ -10,6 +9,7 @@ import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporter
import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters import io.gitlab.jfronny.inceptum.launcher.system.exporter.Exporters
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState import io.gitlab.jfronny.inceptum.launcher.util.ProcessState
import org.gnome.gio.Cancellable
import org.gnome.gtk.* import org.gnome.gtk.*
import java.nio.file.Path import java.nio.file.Path
@ -25,37 +25,20 @@ class ExportTab(private val instance: Instance, window: InstanceSettingsWindow?)
for (exporter in Exporters.EXPORTERS) { for (exporter in Exporters.EXPORTERS) {
row("instance.settings.export.title", "instance.settings.export.subtitle", exporter.name, exporter.fileExtension) { row("instance.settings.export.title", "instance.settings.export.subtitle", exporter.name, exporter.fileExtension) {
setButton("instance.settings.export") { setButton("instance.settings.export") {
val dialog = FileChooserNative( run {
I18n["instance.settings.export.dialog.title", exporter.name], val dialog = FileDialog()
window, dialog.title = I18n["instance.settings.export.dialog.title", exporter.name]
FileChooserAction.SAVE, val filters = AnyFilter()
"_" + I18n["save"], val filter = FileFilter()
"_" + I18n["cancel"] filter.name = exporter.name + " Pack"
) filter.addPattern("*." + exporter.fileExtension)
val filter = FileFilter() filters.append(filter)
filter.name = exporter.name + " Pack" dialog.filters = filters
filter.addPattern("*." + exporter.fileExtension) dialog.initialName = exporter.getDefaultFileName(instance)
dialog.addFilter(filter) dialog.save(window, Cancellable()) { _, res, _ ->
dialog.currentName = exporter.getDefaultFileName(instance) export(exporter, Path.of(dialog.saveFinish(res)?.path ?: return@save))
dialog.onResponse { responseId: Int ->
if (responseId == ResponseType.ACCEPT.value) {
val file = dialog.file!!.path
if (file == null) {
GtkEnvBackend.simpleDialog(
window,
"The path returned by the file dialog is null",
"Could not export",
MessageType.ERROR,
ButtonsType.CLOSE,
null,
null
)
return@onResponse
}
export(exporter, Path.of(file))
} }
} }
dialog.show()
} }
} }
} }
@ -94,7 +77,7 @@ class ExportTab(private val instance: Instance, window: InstanceSettingsWindow?)
else -> {} else -> {}
} }
} }
success.show() success.visible = true
} }
} }
} }

View File

@ -12,6 +12,7 @@ import io.gitlab.jfronny.inceptum.gtk.util.I18n
import io.gitlab.jfronny.inceptum.gtk.util.Memory import io.gitlab.jfronny.inceptum.gtk.util.Memory
import io.gitlab.jfronny.inceptum.gtk.util.markup import io.gitlab.jfronny.inceptum.gtk.util.markup
import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray import io.gitlab.jfronny.inceptum.gtk.util.toTypedArray
import io.gitlab.jfronny.inceptum.gtk.window.create.NewInstanceWindow
import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi import io.gitlab.jfronny.inceptum.launcher.api.FabricMetaApi
import io.gitlab.jfronny.inceptum.launcher.api.McApi import io.gitlab.jfronny.inceptum.launcher.api.McApi
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta import io.gitlab.jfronny.inceptum.launcher.model.inceptum.InstanceMeta
@ -65,8 +66,7 @@ class GeneralTab(instance: Instance, window: InstanceSettingsWindow) : SettingsT
.filter { InceptumConfig.snapshots || it.type == "release" } .filter { InceptumConfig.snapshots || it.type == "release" }
.map { it.id } .map { it.id }
.toTypedArray() .toTypedArray()
var def = 0 val def = versions.withIndex().firstOrNull { it.value == instance.gameVersion }?.index ?: 0
for (i in versions.indices) if (versions[i] == instance.gameVersion) def = i
row("instance.settings.general.game.version", "instance.settings.general.game.version.subtitle") { row("instance.settings.general.game.version", "instance.settings.general.game.version.subtitle") {
setDropdown(versions, def) { i -> setDropdown(versions, def) { i ->
@ -111,7 +111,7 @@ class GeneralTab(instance: Instance, window: InstanceSettingsWindow) : SettingsT
.map { it.loader.version } .map { it.loader.version }
.orElse(null) .orElse(null)
fabricVersions = ver.map { Arrays.stream(it) } fabricVersions = ver.map { Arrays.stream(it) }
.map{ it.map { l -> l.loader.version }.toTypedArray() } .map { it.map { l -> l.loader.version }.toTypedArray() }
.orElse(null) .orElse(null)
if (fabricVersions == null || fabricVersions!!.isEmpty()) { if (fabricVersions == null || fabricVersions!!.isEmpty()) {
fabricEnabled.active = false fabricEnabled.active = false

View File

@ -24,7 +24,7 @@ class AccountsTab(window: Window?) : SettingsTab(window) {
clear() clear()
build() build()
GtkMenubar.generateAccountsMenu(window!!.application!!) GtkMenubar.generateAccountsMenu(window!!.application!!)
}.show() }.visible = true
} }
} }

View File

@ -4,6 +4,7 @@ import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
import io.gitlab.jfronny.inceptum.common.GsonPreset; import io.gitlab.jfronny.inceptum.common.GsonPreset;
import java.util.Date; import java.util.Date;
import java.util.Objects;
@GSerializable(configure = GsonPreset.Api.class) @GSerializable(configure = GsonPreset.Api.class)
public class VersionsListInfo { public class VersionsListInfo {
@ -24,4 +25,9 @@ public class VersionsListInfo {
this.sha1 = vli.sha1; this.sha1 = vli.sha1;
this.complianceLevel = vli.complianceLevel; this.complianceLevel = vli.complianceLevel;
} }
@Override
public boolean equals(Object obj) {
return obj instanceof VersionsListInfo li && Objects.equals(id, li.id);
}
} }