Implement new instance window, bump java and GTK
This commit is contained in:
parent
e9f8af5617
commit
1be0d68a56
|
@ -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")
|
||||||
|
|
|
@ -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")
|
||||||
}
|
}
|
|
@ -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")
|
||||||
|
|
|
@ -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") }
|
|
@ -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 {
|
||||||
|
|
|
@ -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?)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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())
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
|
@ -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() }
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue