Initial work on porting to java-gi, currently broken
This commit is contained in:
parent
fb56c9e922
commit
be8252ce58
|
@ -12,8 +12,7 @@ allprojects {
|
|||
val lwjglVersion by extra("3.3.1")
|
||||
val imguiVersion by extra("1.86.4")
|
||||
val jfCommonsVersion by extra("1.0-SNAPSHOT")
|
||||
val gsonCompileVersion by extra("1.1-SNAPSHOT")
|
||||
val manifoldVersion by extra("2022.1.27")
|
||||
val gsonCompileVersion by extra("1.2-SNAPSHOT")
|
||||
val jlhttpVersion by extra("2.6")
|
||||
|
||||
val flavorProp: String by extra(prop("flavor", "custom"))
|
||||
|
|
|
@ -3,7 +3,7 @@ import de.undercouch.gradle.tasks.download.Download
|
|||
|
||||
plugins {
|
||||
application
|
||||
id("inceptum.java-conventions")
|
||||
id("inceptum.java")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("de.undercouch.download")
|
||||
}
|
||||
|
@ -43,4 +43,8 @@ val nativeExe by tasks.registering(FileOutput::class) {
|
|||
|
||||
if (rootProject.extra["flavor"] == "windows") {
|
||||
tasks.build.get().dependsOn(nativeExe)
|
||||
}
|
||||
|
||||
tasks.runShadow {
|
||||
workingDir = rootProject.projectDir
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
plugins {
|
||||
application
|
||||
id("inceptum.java-conventions")
|
||||
id("inceptum.java")
|
||||
}
|
||||
|
||||
publishing {
|
||||
|
@ -9,4 +9,6 @@ publishing {
|
|||
from(components["java"])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.run.get().workingDir = rootProject.projectDir
|
|
@ -1,7 +1,7 @@
|
|||
import org.gradle.kotlin.dsl.extra
|
||||
|
||||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("inceptum.library")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.java-conventions")
|
||||
id("inceptum.java")
|
||||
}
|
||||
|
||||
publishing {
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.java-conventions")
|
||||
id("inceptum.java")
|
||||
id("jf.manifold")
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import io.gitlab.jfronny.scripts.*
|
|||
import javax.lang.model.element.Modifier
|
||||
|
||||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("inceptum.library")
|
||||
id("jf.codegen")
|
||||
id("inceptum.gson-compile")
|
||||
id("inceptum.manifold")
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.common;
|
||||
|
||||
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.common.InceptumConfig.GC_InceptumConfig;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GComment;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.gson.stream.*;
|
||||
import io.gitlab.jfronny.inceptum.common.model.inceptum.UpdateChannel;
|
||||
|
||||
|
@ -7,14 +10,23 @@ import java.io.IOException;
|
|||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
@GSerializable(configure = GsonPreset.Config.class, isStatic = true)
|
||||
public class InceptumConfig {
|
||||
@GComment("Whether to show snapshots in the version selector for new instances")
|
||||
public static boolean snapshots = false;
|
||||
@GComment("Whether to launch the GUI in dark mode\nConfigurable in Settings->Dark Theme")
|
||||
public static boolean darkTheme = false;
|
||||
@GComment("Whether the GTK UI should default to a list view instead of a grid")
|
||||
public static boolean listView = false;
|
||||
@GComment("Whether to require an account to launch the game\nIntended to allow running the game from USB sticks on constrained networks")
|
||||
public static boolean enforceAccount = true;
|
||||
@GComment("The currently selected account\nUsed to launch the game")
|
||||
public static String lastAccount = null;
|
||||
@GComment("The last name used for an offline session")
|
||||
public static String offlineAccountLastName = null;
|
||||
@GComment("The update channel. Either \"CI\" or \"Stable\"\nI personally recommend the CI channel as it gets the latest fixes and features quicker")
|
||||
public static UpdateChannel channel = UpdateChannel.Stable;
|
||||
@GComment("The author name to add to packs where the metadata format requires specifying one")
|
||||
public static String authorName = "Inceptum";
|
||||
|
||||
public static void load() throws IOException {
|
||||
|
@ -31,78 +43,14 @@ public class InceptumConfig {
|
|||
saveConfig();
|
||||
}
|
||||
}
|
||||
try (JsonReader jr = new JsonReader(Files.newBufferedReader(MetaHolder.CONFIG_PATH))) {
|
||||
GsonPreset.Config.configure(jr);
|
||||
jr.beginObject();
|
||||
while (jr.peek() != JsonToken.END_OBJECT) {
|
||||
String name = null;
|
||||
try {
|
||||
name = jr.nextName();
|
||||
switch (name) {
|
||||
case "snapshots" -> snapshots = jr.nextBoolean();
|
||||
case "darkTheme" -> darkTheme = jr.nextBoolean();
|
||||
case "listView" -> listView = jr.nextBoolean();
|
||||
case "enforceAccount" -> enforceAccount = jr.nextBoolean();
|
||||
case "lastAccount" -> lastAccount = nullableString(jr);
|
||||
case "offlineAccountLastName" -> offlineAccountLastName = nullableString(jr);
|
||||
case "channel" -> {
|
||||
try {
|
||||
channel = UpdateChannel.valueOf(jr.nextString());
|
||||
} catch (IllegalArgumentException e) {
|
||||
Utils.LOGGER.error("Could not read channel", e);
|
||||
}
|
||||
}
|
||||
case "authorName" -> authorName = jr.nextString();
|
||||
default -> {
|
||||
Utils.LOGGER.error("Unexpected entry name: " + name);
|
||||
jr.skipValue();
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
if (name == null) Utils.LOGGER.error("Could not read config entry", t);
|
||||
else Utils.LOGGER.error("Could not read config entry: " + name, t);
|
||||
return;
|
||||
}
|
||||
}
|
||||
jr.endObject();
|
||||
}
|
||||
GC_InceptumConfig.read(MetaHolder.CONFIG_PATH);
|
||||
}
|
||||
|
||||
public static void saveConfig() {
|
||||
try (JsonWriter jw = new JsonWriter(Files.newBufferedWriter(MetaHolder.CONFIG_PATH))) {
|
||||
GsonPreset.Config.configure(jw);
|
||||
jw.beginObject()
|
||||
.comment("Whether to show snapshots in the version selector for new instances")
|
||||
.name("snapshots").value(snapshots)
|
||||
.comment("Whether to launch the GUI in dark mode")
|
||||
.comment("Configurable in Settings->Dark Theme")
|
||||
.name("darkTheme").value(darkTheme)
|
||||
.comment("Whether the GTK UI should default to a list view instead of a grid")
|
||||
.name("listView").value(listView)
|
||||
.comment("Whether to require an account to launch the game")
|
||||
.comment("Intended to allow running the game from USB sticks on constrained networks")
|
||||
.name("enforceAccount").value(enforceAccount)
|
||||
.comment("The currently selected account")
|
||||
.comment("Used to launch the game")
|
||||
.name("lastAccount").value(lastAccount)
|
||||
.comment("The last name used for an offline session")
|
||||
.name("offlineAccountLastName").value(offlineAccountLastName)
|
||||
.comment("The update channel. Either \"CI\" or \"Stable\"")
|
||||
.comment("I personally recommend the CI channel as it gets the latest fixes and features quicker")
|
||||
.name("channel").value(channel.toString())
|
||||
.comment("The author name to add to packs where the metadata format requires specifying one")
|
||||
.name("authorName").value(authorName)
|
||||
.endObject();
|
||||
try {
|
||||
GC_InceptumConfig.write(MetaHolder.CONFIG_PATH);
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not save config", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String nullableString(JsonReader jr) throws IOException {
|
||||
if (jr.peek() == JsonToken.NULL) {
|
||||
jr.nextNull();
|
||||
return null;
|
||||
}
|
||||
return jr.nextString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.application-conventions")
|
||||
id("inceptum.application")
|
||||
id("inceptum.manifold")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.application-standalone-conventions")
|
||||
id("inceptum.application-standalone")
|
||||
}
|
||||
|
||||
application {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
plugins {
|
||||
id("inceptum.application-conventions")
|
||||
id("inceptum.application")
|
||||
id("com.github.johnrengelman.shadow")
|
||||
id("jf.manifold")
|
||||
}
|
||||
|
||||
application {
|
||||
|
@ -8,12 +9,21 @@ application {
|
|||
}
|
||||
|
||||
repositories {
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
mavenLocal()
|
||||
maven { url = uri("https://maven.frohnmeyer-wds.de/java-gi") }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.github.bailuk:java-gtk:0.2")
|
||||
implementation("io.github.jwharm.javagi:gtk4:0.3-SNAPSHOT")
|
||||
implementation("io.github.jwharm.javagi:glib:0.3-SNAPSHOT")
|
||||
implementation(project(":launcher"))
|
||||
}
|
||||
|
||||
tasks.runShadow.get().workingDir = rootProject.projectDir
|
||||
tasks.compileJava {
|
||||
options.compilerArgs.add("--enable-preview")
|
||||
}
|
||||
|
||||
tasks.runShadow {
|
||||
workingDir = rootProject.projectDir
|
||||
jvmArgs!!.addAll(listOf("--enable-preview", "--enable-native-access=ALL-UNNAMED"))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import org.gtk.gtk.*;
|
||||
import io.gitlab.jfronny.commons.StringFormatter;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
||||
|
@ -46,19 +44,19 @@ public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test
|
|||
//TODO run on main thread
|
||||
GtkMain.schedule(() -> {
|
||||
Dialog dialog = new Dialog();
|
||||
if (dialogParent != null) dialog.setTransientFor(dialogParent);
|
||||
dialog.setModal(GTK.TRUE);
|
||||
if (dialogParent != null) dialog.setDestroyWithParent(GTK.TRUE);
|
||||
dialog.setTitle(new Str(prompt));
|
||||
Box box = dialog.getContentArea();
|
||||
box.append(new Label(new Str(details)));
|
||||
if (dialogParent != null) dialog.transientFor = dialogParent;
|
||||
dialog.modal = true;
|
||||
if (dialogParent != null) dialog.destroyWithParent = true;
|
||||
dialog.title = prompt;
|
||||
Box box = dialog.contentArea;
|
||||
box.append(new Label(details));
|
||||
Entry entry = new Entry();
|
||||
Editable entryEditable = new Editable(entry.cast());
|
||||
entryEditable.setText(new Str(defaultValue));
|
||||
Editable entryEditable = Editable.castFrom(entry);
|
||||
entryEditable.text = defaultValue;
|
||||
box.append(entry);
|
||||
dialog.addButton(I18n.str("ok"), ResponseType.OK);
|
||||
dialog.addButton(I18n.str("cancel"), ResponseType.CANCEL);
|
||||
dialog.onResponse(processResponses(dialog, () -> ok.accept(entryEditable.getText().toString()), cancel));
|
||||
dialog.addButton(I18n.get("ok"), ResponseType.OK.getValue());
|
||||
dialog.addButton(I18n.get("cancel"), ResponseType.CANCEL.getValue());
|
||||
dialog.onResponse(processResponses(dialog, () -> ok.accept(entryEditable.text.toString()), cancel));
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
|
@ -68,28 +66,28 @@ public enum GtkEnvBackend implements LauncherEnv.EnvBackend { //TODO test
|
|||
//TODO
|
||||
}
|
||||
|
||||
private void simpleDialog(String markup, String title, int type, int buttons, Runnable ok, Runnable cancel) {
|
||||
private void simpleDialog(String markup, String title, MessageType type, ButtonsType buttons, Runnable ok, Runnable cancel) {
|
||||
GtkMain.schedule(() -> {
|
||||
MessageDialog dialog = new MessageDialog(dialogParent, DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT, type, buttons, null);
|
||||
dialog.setTitle(new Str(title));
|
||||
dialog.setMarkup(new Str(markup));
|
||||
MessageDialog dialog = new MessageDialog(dialogParent, DialogFlags.MODAL.or(DialogFlags.DESTROY_WITH_PARENT), type, buttons, null);
|
||||
dialog.title = title;
|
||||
dialog.markup = markup;
|
||||
dialog.onResponse(processResponses(dialog, ok, cancel));
|
||||
dialog.show();
|
||||
});
|
||||
}
|
||||
|
||||
private Dialog.OnResponse processResponses(Dialog dialog, @Nullable Runnable ok, @Nullable Runnable cancel) {
|
||||
return response_id -> {
|
||||
switch (response_id) {
|
||||
case ResponseType.OK -> {
|
||||
private Dialog.Response processResponses(Dialog dialog, @Nullable Runnable ok, @Nullable Runnable cancel) {
|
||||
return ($, response_id) -> {
|
||||
switch (ResponseType.of(response_id)) {
|
||||
case OK -> {
|
||||
dialog.close();
|
||||
if (ok != null) ok.run();
|
||||
}
|
||||
case ResponseType.CLOSE, ResponseType.CANCEL -> {
|
||||
case CLOSE, CANCEL -> {
|
||||
dialog.close();
|
||||
if (cancel != null) cancel.run();
|
||||
}
|
||||
case ResponseType.DELETE_EVENT -> dialog.destroy();
|
||||
case DELETE_EVENT -> dialog.destroy();
|
||||
default -> Utils.LOGGER.error("Unexpected response type: " + response_id);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gio.ApplicationFlags;
|
||||
import ch.bailu.gtk.glib.Glib;
|
||||
import ch.bailu.gtk.gtk.Application;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import ch.bailu.gtk.type.Strs;
|
||||
import org.gtk.gio.ApplicationFlags;
|
||||
import org.gtk.glib.GLib;
|
||||
import org.gtk.gtk.Application;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.gtk.window.MainWindow;
|
||||
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
||||
|
@ -14,7 +11,7 @@ import java.io.IOException;
|
|||
import java.util.*;
|
||||
|
||||
public class GtkMain {
|
||||
public static final Str ID = new Str("io.gitlab.jfronny.inceptum");
|
||||
public static final String ID = "io.gitlab.jfronny.inceptum";
|
||||
private static final Queue<Runnable> SCHEDULED = new ArrayDeque<>();
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
@ -37,11 +34,11 @@ public class GtkMain {
|
|||
|
||||
public static int showGui(String[] args) throws IOException {
|
||||
var app = new Application(ID, ApplicationFlags.FLAGS_NONE);
|
||||
app.onActivate(() -> {
|
||||
app.onActivate($ -> {
|
||||
GtkMenubar.create(app);
|
||||
var window = new MainWindow(app);
|
||||
window.show();
|
||||
Glib.idleAdd(user_data -> {
|
||||
GLib.idleAdd(data -> {
|
||||
Runnable r;
|
||||
while ((r = SCHEDULED.poll()) != null) {
|
||||
try {
|
||||
|
@ -50,14 +47,15 @@ public class GtkMain {
|
|||
Utils.LOGGER.error("Could not run scheduled task", t);
|
||||
}
|
||||
}
|
||||
return GTK.TRUE;
|
||||
return true;
|
||||
}, null);
|
||||
GtkEnvBackend.INSTANCE.dialogParent = window;
|
||||
window.onCloseRequest(() -> {
|
||||
window.onCloseRequest($1 -> {
|
||||
GtkEnvBackend.INSTANCE.dialogParent = null;
|
||||
return GTK.FALSE;
|
||||
app.quit();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
return app.run(args.length, new Strs(args));
|
||||
return app.run(args.length, args);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk;
|
||||
|
||||
import ch.bailu.gtk.gtk.Application;
|
||||
import org.gtk.gtk.Application;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder;
|
||||
|
@ -63,11 +63,11 @@ public class GtkMenubar {
|
|||
}
|
||||
InstanceLauncher.launchClient(instance);
|
||||
};
|
||||
if (instance.isSetupLocked()) {
|
||||
if (instance.isSetupLocked) {
|
||||
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
|
||||
return;
|
||||
}
|
||||
if (instance.isRunningLocked()) {
|
||||
if (instance.isRunningLocked) {
|
||||
LauncherEnv.showOkCancel(I18n.get("instance.launch.locked.running"), I18n.get("instance.launch.locked"), () -> {
|
||||
new Thread(launch).start(); //TODO loom
|
||||
}, R::nop);
|
||||
|
@ -84,9 +84,9 @@ public class GtkMenubar {
|
|||
accountsMenu.button("manage", () -> {
|
||||
//TODO UI to add/remove accounts
|
||||
});
|
||||
List<MicrosoftAccount> accounts = new ArrayList<>(AccountManager.getAccounts());
|
||||
List<MicrosoftAccount> accounts = new ArrayList<>(AccountManager.accounts);
|
||||
accounts.add(null);
|
||||
accountsMenu.literalRadio("account", accounts.get(AccountManager.getSelectedIndex()), accounts, (i, acc) -> {
|
||||
accountsMenu.literalRadio("account", accounts.get(AccountManager.selectedIndex), accounts, (i, acc) -> {
|
||||
if (acc == null) return I18n.get("account.none");
|
||||
return acc.minecraftUsername;
|
||||
}, AccountManager::switchAccount);
|
||||
|
|
|
@ -1,34 +1,31 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gio.ApplicationFlags;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import ch.bailu.gtk.type.Strs;
|
||||
import org.gtk.gio.ApplicationFlags;
|
||||
import org.gtk.gtk.*;
|
||||
import io.gitlab.jfronny.commons.ref.R;
|
||||
|
||||
public class TestStart {
|
||||
public static void main(String[] args) {
|
||||
var app = new Application(GtkMain.ID, ApplicationFlags.FLAGS_NONE);
|
||||
app.onActivate(() -> {
|
||||
var button = Button.newWithLabelButton(new Str("Test"));
|
||||
app.onActivate($ -> {
|
||||
var button = Button.newWithLabel("Test");
|
||||
button.onClicked(TestStart::test);
|
||||
|
||||
var window = new ApplicationWindow(app);
|
||||
window.setDefaultSize(200, 50);
|
||||
window.setTitle(new Str("Inceptum"));
|
||||
window.setChild(button);
|
||||
window.title = "Inceptum";
|
||||
window.child = button;
|
||||
window.show();
|
||||
GtkEnvBackend.INSTANCE.dialogParent = window;
|
||||
window.onCloseRequest(() -> {
|
||||
window.onCloseRequest($1 -> {
|
||||
GtkEnvBackend.INSTANCE.dialogParent = null;
|
||||
return GTK.FALSE;
|
||||
return false;
|
||||
});
|
||||
});
|
||||
System.exit(app.run(args.length, new Strs(args)));
|
||||
System.exit(app.run(args.length, args));
|
||||
}
|
||||
|
||||
private static void test() {
|
||||
private static void test(Button $) {
|
||||
GtkEnvBackend backend = GtkEnvBackend.INSTANCE;
|
||||
|
||||
backend.getInput("Ae", "IoU\naee", "Def", R::nop, R::nop);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public interface DisposeCallback {
|
||||
void upcall(MemoryAddress pointer);
|
||||
|
||||
@ApiStatus.Internal
|
||||
FunctionDescriptor DESCRIPTOR = FunctionDescriptor.ofVoid(Interop.valueLayout.ADDRESS);
|
||||
@ApiStatus.Internal
|
||||
MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), DisposeCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.Addressable;
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface GetItemCallback {
|
||||
Addressable upcall(MemoryAddress inst, int position);
|
||||
|
||||
@ApiStatus.Internal FunctionDescriptor DESCRIPTOR = FunctionDescriptor.of(Interop.valueLayout.ADDRESS, Interop.valueLayout.ADDRESS, Interop.valueLayout.C_INT);
|
||||
@ApiStatus.Internal MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), GetItemCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public interface GetItemTypeCallback {
|
||||
long upcall(MemoryAddress address);
|
||||
|
||||
@ApiStatus.Internal
|
||||
FunctionDescriptor DESCRIPTOR = FunctionDescriptor.of(Interop.valueLayout.C_LONG, Interop.valueLayout.ADDRESS);
|
||||
@ApiStatus.Internal
|
||||
MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), GetItemTypeCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public interface GetNItemsCallback {
|
||||
int upcall(MemoryAddress inst);
|
||||
|
||||
@ApiStatus.Internal
|
||||
FunctionDescriptor DESCRIPTOR = FunctionDescriptor.of(Interop.valueLayout.C_INT, Interop.valueLayout.ADDRESS);
|
||||
@ApiStatus.Internal
|
||||
MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), GetNItemsCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import io.github.jwharm.javagi.Marshal;
|
||||
import io.github.jwharm.javagi.Ownership;
|
||||
import org.gtk.gobject.GiObject;
|
||||
import org.gtk.gobject.ParamSpec;
|
||||
import org.gtk.gobject.Value;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public interface GetPropertyCallback {
|
||||
void invoke(GiObject object, int propertyId, Value value, ParamSpec paramSpec);
|
||||
|
||||
default void upcall(MemoryAddress object, int propertyId, MemoryAddress value, MemoryAddress pspec) {
|
||||
invoke(GiObject.fromAddress.marshal(object, Ownership.NONE),
|
||||
propertyId,
|
||||
Value.fromAddress.marshal(value, Ownership.NONE),
|
||||
ParamSpec.fromAddress.marshal(pspec, Ownership.NONE));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
FunctionDescriptor DESCRIPTOR = FunctionDescriptor.ofVoid(Interop.valueLayout.ADDRESS, Interop.valueLayout.C_INT, Interop.valueLayout.ADDRESS, Interop.valueLayout.ADDRESS);
|
||||
@ApiStatus.Internal
|
||||
MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), GetPropertyCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.callback;
|
||||
|
||||
import io.github.jwharm.javagi.CallbackGenerator;
|
||||
import io.github.jwharm.javagi.Interop;
|
||||
import io.github.jwharm.javagi.Marshal;
|
||||
import io.github.jwharm.javagi.Ownership;
|
||||
import org.gtk.gobject.GiObject;
|
||||
import org.gtk.gobject.ParamSpec;
|
||||
import org.gtk.gobject.Value;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.lang.foreign.FunctionDescriptor;
|
||||
import java.lang.foreign.Linker;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
|
||||
public interface SetPropertyCallback {
|
||||
void invoke(GiObject object, int propertyId, Value value, ParamSpec paramSpec);
|
||||
|
||||
default void upcall(MemoryAddress object, int propertyId, MemoryAddress value, MemoryAddress pspec) {
|
||||
invoke(GiObject.fromAddress.marshal(object, Ownership.NONE),
|
||||
propertyId,
|
||||
Value.fromAddress.marshal(value, Ownership.NONE),
|
||||
ParamSpec.fromAddress.marshal(pspec, Ownership.NONE));
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
FunctionDescriptor DESCRIPTOR = FunctionDescriptor.ofVoid(Interop.valueLayout.ADDRESS, Interop.valueLayout.C_INT, Interop.valueLayout.ADDRESS, Interop.valueLayout.ADDRESS);
|
||||
@ApiStatus.Internal
|
||||
MethodHandle HANDLE = CallbackGenerator.getHandle(MethodHandles.lookup(), SetPropertyCallback.class, DESCRIPTOR);
|
||||
|
||||
default MemoryAddress toCallback() {
|
||||
return Linker.nativeLinker().upcallStub(HANDLE.bindTo(this), DESCRIPTOR, Interop.getScope()).address();
|
||||
}
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.control;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.bridge.ListIndex;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.pango.EllipsizeMode;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.ListIndex;
|
||||
import org.gtk.gtk.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import org.pango.EllipsizeMode;
|
||||
import org.pango.WrapMode;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -13,24 +12,24 @@ public class InstanceGridEntryFactory extends SignalListItemFactory {
|
|||
public InstanceGridEntryFactory(List<Instance> instanceList) {
|
||||
super();
|
||||
//TODO better design
|
||||
onSetup(item -> {
|
||||
onSetup(($, item) -> {
|
||||
var box = new Box(Orientation.VERTICAL, 5);
|
||||
|
||||
var thumbnail = new InstanceThumbnail();
|
||||
box.append(thumbnail);
|
||||
|
||||
var label = new Label(Str.NULL);
|
||||
var label = new Label(null);
|
||||
label.setSizeRequest(192, -1);
|
||||
label.setMaxWidthChars(20);
|
||||
label.setJustify(Justification.CENTER);
|
||||
label.setHalign(Align.START);
|
||||
label.setHexpand(GTK.TRUE);
|
||||
label.setValign(Align.CENTER);
|
||||
label.setEllipsize(EllipsizeMode.MIDDLE);
|
||||
label.setLines(3);
|
||||
label.setWrap(GTK.TRUE);
|
||||
label.setWrapMode(WrapMode.WORD_CHAR);
|
||||
label.setMarginTop(10);
|
||||
label.maxWidthChars = 20;
|
||||
label.justify = Justification.CENTER;
|
||||
label.halign = Align.START;
|
||||
label.hexpand = true;
|
||||
label.valign = Align.CENTER;
|
||||
label.ellipsize = EllipsizeMode.MIDDLE;
|
||||
label.lines = 3;
|
||||
label.wrap = true;
|
||||
label.wrapMode = WrapMode.WORD_CHAR;
|
||||
label.marginTop = 10;
|
||||
box.append(label);
|
||||
// Label label = new Label(Str.NULL);
|
||||
// label.setXalign(0);
|
||||
|
@ -50,11 +49,11 @@ public class InstanceGridEntryFactory extends SignalListItemFactory {
|
|||
// openDir.setHasTooltip(GTK.TRUE);
|
||||
// box.append(openDir);
|
||||
|
||||
item.setChild(box);
|
||||
ListItem.castFrom(item).setChild(box);
|
||||
//TODO server launch with network-server-symbolic
|
||||
//TODO kill current instance
|
||||
});
|
||||
onBind(item -> {
|
||||
onBind(($, item) -> {
|
||||
// Label label = new Label(item.getChild().getFirstChild().cast());
|
||||
// Button launch = new Button(label.getNextSibling().cast());
|
||||
// Button openDir = new Button(launch.getNextSibling().cast());
|
||||
|
@ -62,13 +61,16 @@ public class InstanceGridEntryFactory extends SignalListItemFactory {
|
|||
// label.setText(new Str(instance.toString()));
|
||||
// launch.onClicked(() -> GtkMenubar.launch(instance));
|
||||
// openDir.onClicked(() -> Utils.openFile(instance.path().toFile()));
|
||||
Box box = new Box(item.getChild().cast());
|
||||
InstanceThumbnail thumbnail = new InstanceThumbnail(box.getFirstChild().cast());
|
||||
Label label = new Label(thumbnail.getNextSibling().cast());
|
||||
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(item));
|
||||
ListItem li = ListItem.castFrom(item);
|
||||
|
||||
Box box = Box.castFrom(li.getChild());
|
||||
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom(box.firstChild);
|
||||
Label label = Label.castFrom(thumbnail.nextSibling);
|
||||
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(li));
|
||||
thumbnail.bind(instance);
|
||||
label.setText(new Str(instance.toString()));
|
||||
label.text = instance.toString();
|
||||
//TODO right click menu + double click action
|
||||
//TODO edit button document-edit-symbolic -> edit-delete-symbolic, edit-copy-symbolic
|
||||
});
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.control;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.adw.ActionRow;
|
||||
import ch.bailu.gtk.bridge.ListIndex;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.ListIndex;
|
||||
import org.gnome.adw.ActionRow;
|
||||
import org.gtk.gtk.*;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
||||
|
@ -15,44 +13,46 @@ import java.util.List;
|
|||
public class InstanceListEntryFactory extends SignalListItemFactory {
|
||||
public InstanceListEntryFactory(List<Instance> instanceList) {
|
||||
super();
|
||||
onSetup(item -> {
|
||||
onSetup(($, item) -> {
|
||||
var thumbnail = new InstanceThumbnail();
|
||||
thumbnail.setName(new Str("inceptum-thumbnail"));
|
||||
thumbnail.name = "inceptum-thumbnail";
|
||||
|
||||
var launch = new Button();
|
||||
launch.setName(new Str("inceptum-launch"));
|
||||
launch.setIconName(new Str("computer-symbolic"));
|
||||
launch.setTooltipText(I18n.str("instance.launch"));
|
||||
launch.setHasTooltip(GTK.TRUE);
|
||||
launch.name = "inceptum-launch";
|
||||
launch.iconName = "computer-symbolic";
|
||||
launch.tooltipText = I18n.get("instance.launch");
|
||||
launch.hasTooltip = true;
|
||||
|
||||
var openDir = new Button();
|
||||
openDir.setName(new Str("inceptum-open-dir"));
|
||||
openDir.setIconName(new Str("folder-symbolic"));
|
||||
openDir.setTooltipText(I18n.str("instance.directory"));
|
||||
openDir.setHasTooltip(GTK.TRUE);
|
||||
openDir.name = "inceptum-open-dir";
|
||||
openDir.iconName = "folder-symbolic";
|
||||
openDir.tooltipText = I18n.get("instance.directory");
|
||||
openDir.hasTooltip = true;
|
||||
|
||||
var row = new ActionRow();
|
||||
row.setName(new Str("inceptum-row"));
|
||||
row.setActivatableWidget(launch);
|
||||
row.name = "inceptum-row";
|
||||
row.activatableWidget = launch;
|
||||
row.addPrefix(thumbnail);
|
||||
row.addSuffix(launch);
|
||||
row.addSuffix(openDir);
|
||||
|
||||
item.setChild(row);
|
||||
ListItem.castFrom(item).setChild(row);
|
||||
|
||||
//TODO server launch with network-server-symbolic
|
||||
//TODO kill current instance
|
||||
});
|
||||
onBind(item -> {
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(item));
|
||||
ActionRow row = new ActionRow(item.getChild().cast());
|
||||
Box prefixes = new Box(row.getFirstChild().getFirstChild().cast());
|
||||
Box suffixes = new Box(row.getFirstChild().getLastChild().cast());
|
||||
onBind(($, item) -> {
|
||||
ListItem li = ListItem.castFrom(item);
|
||||
|
||||
InstanceThumbnail thumbnail = new InstanceThumbnail(prefixes.getFirstChild().cast());
|
||||
Button launch = new Button(suffixes.getFirstChild().cast());
|
||||
Button openDir = new Button(launch.getNextSibling().cast());
|
||||
row.setTitle(new Str(instance.toString()));
|
||||
Instance instance = instanceList.get(ListIndex.toIndex(li));
|
||||
ActionRow row = ActionRow.castFrom(li.child);
|
||||
Box prefixes = Box.castFrom(row.firstChild.firstChild);
|
||||
Box suffixes = Box.castFrom(row.firstChild.lastChild);
|
||||
|
||||
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom(prefixes.firstChild);
|
||||
Button launch = Button.castFrom(suffixes.firstChild);
|
||||
Button openDir = Button.castFrom(launch.nextSibling);
|
||||
row.title = instance.toString();
|
||||
|
||||
// InstanceThumbnail thumbnail = new InstanceThumbnail(row.getFirstChild().cast());
|
||||
// Label label = new Label(thumbnail.getNextSibling().cast());
|
||||
|
@ -61,8 +61,8 @@ public class InstanceListEntryFactory extends SignalListItemFactory {
|
|||
|
||||
thumbnail.bind(instance);
|
||||
// label.setText(new Str(instance.toString()));
|
||||
launch.onClicked(() -> GtkMenubar.launch(instance));
|
||||
openDir.onClicked(() -> Utils.openFile(instance.path().toFile()));
|
||||
launch.onClicked($1 -> GtkMenubar.launch(instance));
|
||||
openDir.onClicked($1 -> Utils.openFile(instance.path().toFile()));
|
||||
|
||||
//TODO why the hell does this crash the VM?
|
||||
//TODO GestureClick.setButton(GDK_BUTTON_SECONDARY)
|
||||
|
|
|
@ -1,16 +1,30 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.control;
|
||||
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.*;
|
||||
import io.github.jwharm.javagi.Ownership;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import org.gtk.gobject.GObject;
|
||||
import org.gtk.gobject.TypeInstance;
|
||||
import org.gtk.gtk.Image;
|
||||
import org.gtk.gtk.Spinner;
|
||||
import org.gtk.gtk.Stack;
|
||||
|
||||
import java.lang.foreign.Addressable;
|
||||
|
||||
public class InstanceThumbnail extends Stack {
|
||||
private static final Str SPINNER = new Str("spinner");
|
||||
private static final Str IMAGE = new Str("image");
|
||||
private static final Str GENERIC = new Str("generic");
|
||||
private static final String SPINNER = "spinner";
|
||||
private static final String IMAGE = "image";
|
||||
private static final String GENERIC = "generic";
|
||||
|
||||
public InstanceThumbnail(CPointer pointer) {
|
||||
super(pointer);
|
||||
private InstanceThumbnail(Addressable address, Ownership ownership) {
|
||||
super(address, ownership);
|
||||
}
|
||||
|
||||
public static InstanceThumbnail castFrom(org.gtk.gobject.GiObject gobject) {
|
||||
if (GObject.typeCheckInstanceIsA(TypeInstance.fromAddress.marshal(gobject.handle(), Ownership.NONE), Stack.getType())) {
|
||||
return new InstanceThumbnail(gobject.handle(), gobject.yieldOwnership());
|
||||
} else {
|
||||
throw new ClassCastException("Object type is not an instance of GtkStack");
|
||||
}
|
||||
}
|
||||
|
||||
public InstanceThumbnail() {
|
||||
|
@ -18,26 +32,26 @@ public class InstanceThumbnail extends Stack {
|
|||
var spinner = new Spinner();
|
||||
var image = new Image();
|
||||
var generic = new Image();
|
||||
spinner.setName(SPINNER);
|
||||
image.setName(IMAGE);
|
||||
generic.setName(GENERIC);
|
||||
generic.setFromIconName(new Str("media-playback-start-symbolic")); //TODO better default icon
|
||||
spinner.name = SPINNER;
|
||||
image.name = IMAGE;
|
||||
generic.name = GENERIC;
|
||||
generic.setFromIconName("media-playback-start-symbolic"); //TODO better default icon
|
||||
addNamed(spinner, SPINNER);
|
||||
addNamed(image, IMAGE);
|
||||
addNamed(generic, GENERIC);
|
||||
}
|
||||
|
||||
public void bind(Instance entry) {
|
||||
var spinner = new Spinner(getChildByName(SPINNER).cast());
|
||||
var image = new Image(getChildByName(IMAGE).cast()); //TODO
|
||||
var generic = new Image(getChildByName(GENERIC).cast());
|
||||
var spinner = Spinner.castFrom(getChildByName(SPINNER));
|
||||
var image = Image.castFrom(getChildByName(IMAGE)); //TODO
|
||||
var generic = Image.castFrom(getChildByName(GENERIC));
|
||||
//TODO mark instance being played
|
||||
if (entry.isSetupLocked()) {
|
||||
setVisibleChild(spinner);
|
||||
if (entry.isSetupLocked) {
|
||||
visibleChild = spinner;
|
||||
} else if (false) { // if the instance has an image, load the image data and set it as the visible child
|
||||
setVisibleChild(image);
|
||||
visibleChild = image;
|
||||
} else {
|
||||
setVisibleChild(generic);
|
||||
visibleChild = generic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||
|
||||
import ch.bailu.gtk.gio.SimpleAction;
|
||||
import org.gtk.gio.SimpleAction;
|
||||
|
||||
public class ButtonItem extends MenuItem {
|
||||
public ButtonItem(SimpleAction action) {
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gio.MenuItem;
|
||||
import ch.bailu.gtk.gio.*;
|
||||
import ch.bailu.gtk.glib.Variant;
|
||||
import ch.bailu.gtk.glib.VariantType;
|
||||
import ch.bailu.gtk.gtk.Application;
|
||||
import ch.bailu.gtk.gtk.PopoverMenu;
|
||||
import ch.bailu.gtk.type.Pointer;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import io.gitlab.jfronny.commons.throwable.ThrowingRunnable;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
||||
import org.gtk.gio.MenuItem;
|
||||
import org.gtk.gio.*;
|
||||
import org.gtk.glib.Variant;
|
||||
import org.gtk.glib.VariantType;
|
||||
import org.gtk.gtk.Application;
|
||||
import org.gtk.gtk.PopoverMenu;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
@ -22,13 +22,13 @@ public class MenuBuilder {
|
|||
|
||||
private static Menu getRootMenu(Application app) {
|
||||
synchronized (LOCK) {
|
||||
var currentMenu = app.getMenubar();
|
||||
if (currentMenu.equals(Pointer.NULL)) {
|
||||
var currentMenu = app.menubar;
|
||||
if (currentMenu == null) {
|
||||
var menu = new Menu();
|
||||
app.setMenubar(menu);
|
||||
app.menubar = menu;
|
||||
return menu;
|
||||
} else {
|
||||
return new Menu(currentMenu.cast());
|
||||
return Menu.castFrom(currentMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,10 +42,6 @@ public class MenuBuilder {
|
|||
this(app, getRootMenu(app), "");
|
||||
}
|
||||
|
||||
public MenuBuilder(Application app, Menu menu, String prefix) {
|
||||
this(new ActionMap(app.cast()), menu, prefix);
|
||||
}
|
||||
|
||||
public MenuBuilder(ActionMap map, Menu menu, String prefix) {
|
||||
if (!prefix.isEmpty() && !prefix.endsWith(".")) prefix += ".";
|
||||
this.map = Objects.requireNonNull(map);
|
||||
|
@ -59,29 +55,29 @@ public class MenuBuilder {
|
|||
|
||||
public ButtonItem literalButton(String internalName, String label, ThrowingRunnable<?> onClick) {
|
||||
internalName = prefix + internalName;
|
||||
SimpleAction sAct = new SimpleAction(new Str(internalName), null);
|
||||
SimpleAction sAct = new SimpleAction(internalName, null);
|
||||
addAction(internalName, sAct);
|
||||
sAct.onActivate(v -> {
|
||||
sAct.onActivate(($, variant) -> {
|
||||
try {
|
||||
onClick.run();
|
||||
} catch (Throwable e) {
|
||||
Utils.LOGGER.error("Could not execute action", e);
|
||||
}
|
||||
});
|
||||
menu.appendItem(new MenuItem(new Str(label), new Str("app." + internalName)));
|
||||
menu.appendItem(new MenuItem(label, "app." + internalName));
|
||||
return new ButtonItem(sAct);
|
||||
}
|
||||
|
||||
public ToggleItem toggle(String name, boolean initial, Consumer<Boolean> action) {
|
||||
name = prefix + name;
|
||||
SimpleAction sAct = SimpleAction.newStatefulSimpleAction(new Str(name), null, Variant.newBooleanVariant(GTK.is(initial)));
|
||||
Action rAct = addAction(name, sAct);
|
||||
sAct.onActivate(parameter -> {
|
||||
boolean state = !GTK.is(rAct.getState().getBoolean());
|
||||
sAct.setState(Variant.newBooleanVariant(GTK.is(state)));
|
||||
SimpleAction sAct = SimpleAction.newStateful(name, null, Variant.newBoolean(initial));
|
||||
addAction(name, sAct);
|
||||
sAct.onActivate(($, variant) -> {
|
||||
boolean state = !sAct.getState().getBoolean();
|
||||
sAct.state = Variant.newBoolean(state);
|
||||
action.accept(state);
|
||||
});
|
||||
menu.appendItem(new MenuItem(I18n.str("menu." + name), new Str("app." + name)));
|
||||
menu.appendItem(new MenuItem(I18n.get("menu." + name), "app." + name));
|
||||
return new ToggleItem(sAct);
|
||||
}
|
||||
|
||||
|
@ -92,15 +88,15 @@ public class MenuBuilder {
|
|||
public <T> RadioItem<T> literalRadio(String name, T initial, List<T> options, BiFunction<Integer, T, String> stringifier, Consumer<T> action) {
|
||||
Objects.requireNonNull(options);
|
||||
name = prefix + name;
|
||||
SimpleAction sAct = SimpleAction.newStatefulSimpleAction(new Str(name), new VariantType(new Str("i")), Variant.newInt32Variant(options.indexOf(initial)));
|
||||
SimpleAction sAct = SimpleAction.newStateful(name, new VariantType("i"), Variant.newInt32(options.indexOf(initial)));
|
||||
addAction(name, sAct);
|
||||
sAct.onActivate(parameter -> {
|
||||
sAct.setState(parameter);
|
||||
action.accept(options.get(parameter.getInt32()));
|
||||
sAct.onActivate(($, variant) -> {
|
||||
sAct.state = variant;
|
||||
action.accept(options.get(variant.getInt32()));
|
||||
});
|
||||
int i = 0;
|
||||
for (T option : options) {
|
||||
menu.appendItem(new MenuItem(new Str(stringifier.apply(i, option)), new Str("app." + name + "(" + i + ")")));
|
||||
menu.appendItem(new MenuItem(stringifier.apply(i, option), "app." + name + "(" + i + ")"));
|
||||
i++;
|
||||
}
|
||||
return new RadioItem<>(sAct, options);
|
||||
|
@ -109,23 +105,21 @@ public class MenuBuilder {
|
|||
public MenuBuilder submenu(String name) {
|
||||
name = prefix + name;
|
||||
Menu submenu = new Menu();
|
||||
menu.appendSubmenu(I18n.str("menu." + name), submenu);
|
||||
menu.appendSubmenu(I18n.get("menu." + name), submenu);
|
||||
return new MenuBuilder(map, submenu, name);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
menu.removeAll();
|
||||
refs.forEach((name, action) -> {
|
||||
map.removeAction(new Str(name));
|
||||
map.removeAction(name);
|
||||
});
|
||||
refs.clear();
|
||||
}
|
||||
|
||||
private Action addAction(String name, SimpleAction action) {
|
||||
Action rAct = new Action(action.cast());
|
||||
map.addAction(rAct);
|
||||
refs.put(name, rAct);
|
||||
return rAct;
|
||||
private void addAction(String name, SimpleAction action) {
|
||||
map.addAction(action);
|
||||
refs.put(name, action);
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
|
@ -133,6 +127,6 @@ public class MenuBuilder {
|
|||
}
|
||||
|
||||
public PopoverMenu asPopover() {
|
||||
return PopoverMenu.newFromModelPopoverMenu(menu);
|
||||
return PopoverMenu.newFromModel(menu);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,19 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gio.Action;
|
||||
import ch.bailu.gtk.gio.SimpleAction;
|
||||
import org.gtk.gio.SimpleAction;
|
||||
|
||||
public abstract class MenuItem {
|
||||
protected final SimpleAction sAction;
|
||||
protected final Action action;
|
||||
protected final SimpleAction action;
|
||||
|
||||
public MenuItem(SimpleAction action) {
|
||||
this.sAction = action;
|
||||
this.action = new Action(action.cast());
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public boolean getEnabled() {
|
||||
return GTK.is(action.getEnabled());
|
||||
return action.getEnabled();
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
sAction.setEnabled(GTK.is(enabled));
|
||||
action.enabled = enabled;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||
|
||||
import ch.bailu.gtk.gio.SimpleAction;
|
||||
import ch.bailu.gtk.glib.Variant;
|
||||
import org.gtk.gio.SimpleAction;
|
||||
import org.gtk.glib.Variant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -14,7 +14,7 @@ public class RadioItem<T> extends MenuItem {
|
|||
}
|
||||
|
||||
public void setSelected(T selected) {
|
||||
sAction.setState(Variant.newInt32Variant(options.indexOf(selected)));
|
||||
action.setState(Variant.newInt32(options.indexOf(selected)));
|
||||
}
|
||||
|
||||
public T getSelected() {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.gio.SimpleAction;
|
||||
import ch.bailu.gtk.glib.Variant;
|
||||
import org.gtk.gio.SimpleAction;
|
||||
import org.gtk.glib.Variant;
|
||||
|
||||
public class ToggleItem extends MenuItem {
|
||||
public ToggleItem(SimpleAction action) {
|
||||
|
@ -10,11 +9,11 @@ public class ToggleItem extends MenuItem {
|
|||
}
|
||||
|
||||
public boolean getState() {
|
||||
return GTK.is(action.getState().getBoolean());
|
||||
return action.getState().getBoolean();
|
||||
}
|
||||
|
||||
public void setState(boolean state) {
|
||||
sAction.setState(Variant.newBooleanVariant(GTK.is(state)));
|
||||
action.state = Variant.newBoolean(state);
|
||||
}
|
||||
|
||||
public boolean toggle() {
|
||||
|
|
|
@ -1,31 +1,23 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.util;
|
||||
|
||||
import ch.bailu.gtk.gtk.Widget;
|
||||
import ch.bailu.gtk.type.Pointer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import org.gtk.gtk.Widget;
|
||||
|
||||
public class Dbg {
|
||||
public static String inspect(Widget ptr) {
|
||||
if (ptr.isNull()) return "<null>";
|
||||
if (ptr == null) return "<null>";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
inspect(ptr, sb, "");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static void inspect(Widget ptr, StringBuilder bld, String indent) {
|
||||
bld.append(indent).append("<").append(ptr.getName().toString()).append("#").append(ptr.getCPointer()).append("> ")
|
||||
.append(Arrays.stream(Pointer.toJnaPointer(ptr.getCssClasses().getCPointer()).getPointerArray(0))
|
||||
.map(p -> p.getString(0))
|
||||
.collect(Collectors.joining(", ")));
|
||||
ptr = ptr.getFirstChild();
|
||||
if (ptr.isNotNull()) {
|
||||
while (ptr.isNotNull()) {
|
||||
bld.append("\n");
|
||||
inspect(ptr, bld, indent + " ");
|
||||
ptr = ptr.getNextSibling();
|
||||
}
|
||||
bld.append(indent).append("<").append(ptr.name).append("#").append(ptr.handle()).append("> ")
|
||||
.append(ptr.getCssClasses().get());
|
||||
ptr = ptr.firstChild;
|
||||
while (ptr != null) {
|
||||
bld.append("\n");
|
||||
inspect(ptr, bld, indent + " ");
|
||||
ptr = ptr.nextSibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.util;
|
||||
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import org.jetbrains.annotations.PropertyKey;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
@ -16,12 +15,4 @@ public class I18n {
|
|||
public static String get(@PropertyKey(resourceBundle = BUNDLE) String key, Object... args) {
|
||||
return String.format(bundle.getString(key), args);
|
||||
}
|
||||
|
||||
public static Str str(@PropertyKey(resourceBundle = BUNDLE) String key) {
|
||||
return new Str(get(key));
|
||||
}
|
||||
|
||||
public static Str str(@PropertyKey(resourceBundle = BUNDLE) String key, Object... args) {
|
||||
return new Str(get(key, args));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.util;
|
||||
|
||||
import io.github.jwharm.javagi.*;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkMain;
|
||||
import io.gitlab.jfronny.inceptum.gtk.callback.*;
|
||||
import org.gtk.gio.ListModel;
|
||||
import org.gtk.gio.ListModelInterface;
|
||||
import org.gtk.glib.Type;
|
||||
import org.gtk.gobject.*;
|
||||
import org.gtk.gtk.*;
|
||||
|
||||
import java.lang.foreign.*;
|
||||
import java.lang.invoke.VarHandle;
|
||||
|
||||
public class ListIndex extends GiObject {
|
||||
private static final int PROP_ITEM_TYPE = 1;
|
||||
private static final String PROP_NAME = "item-type";
|
||||
private static final String TYPE_NAME = "ListIndex";
|
||||
private static final Type PARENT_TYPE = GiObject.getType();
|
||||
|
||||
private static final MemoryLayout memoryLayout = MemoryLayout.structLayout(
|
||||
GiObject.getMemoryLayout().withName("parent_instance"),
|
||||
Interop.valueLayout.C_INT.withName("index"),
|
||||
Interop.valueLayout.C_INT.withName("size")
|
||||
).withName(TYPE_NAME);
|
||||
|
||||
private static Type type;
|
||||
public static Type getType() {
|
||||
if (type == null) {
|
||||
// Register the new gtype
|
||||
type = GObject.typeRegisterStaticSimple(
|
||||
PARENT_TYPE,
|
||||
TYPE_NAME,
|
||||
(short) ObjectClass.getMemoryLayout().byteSize(),
|
||||
classInit,
|
||||
(short) memoryLayout.byteSize(),
|
||||
instanceInit,
|
||||
TypeFlags.NONE
|
||||
);
|
||||
GObject.typeAddInterfaceStatic(type, ListModel.getType(), InterfaceInfo.builder()
|
||||
.setInterfaceInit(interfaceInit)
|
||||
.setInterfaceData(null)
|
||||
.setInterfaceFinalize(null)
|
||||
.build());
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static final VarHandle index = memoryLayout.varHandle(MemoryLayout.PathElement.groupElement("index"));
|
||||
private static final VarHandle size = memoryLayout.varHandle(MemoryLayout.PathElement.groupElement("size"));
|
||||
|
||||
public static ListIndex castFrom(GiObject gobject) {
|
||||
if (GObject.typeCheckInstanceIsA(TypeInstance.fromAddress.marshal(gobject.handle(), Ownership.NONE), getType())) {
|
||||
return new ListIndex(gobject.handle(), gobject.yieldOwnership());
|
||||
} else {
|
||||
throw new ClassCastException("Object type is not an instance of ListIndex");
|
||||
}
|
||||
}
|
||||
|
||||
public static final Marshal<Addressable, ListIndex> fromAddress = (input, ownership) -> input.equals(MemoryAddress.NULL) ? null : new ListIndex(input, ownership);
|
||||
protected ListIndex(Addressable address, Ownership ownership) {
|
||||
super(address, ownership);
|
||||
}
|
||||
|
||||
public ListIndex(int size) {
|
||||
this();
|
||||
setSize(size);
|
||||
}
|
||||
|
||||
public ListIndex() {
|
||||
super(new GiObject(getType(), PROP_NAME, getType()).handle(),
|
||||
Ownership.FULL);
|
||||
}
|
||||
|
||||
private static final InstanceInitFunc instanceInit = (instance, gClass) -> fromAddress.marshal(instance.handle(), Ownership.NONE).initInstance();
|
||||
|
||||
private void initInstance() {
|
||||
setIndex(0);
|
||||
setSize(0);
|
||||
}
|
||||
|
||||
private static TypeClass parentClass = null;
|
||||
private static final DisposeCallback instanceDispose = pointer -> {
|
||||
if (parentClass == null) System.out.println("ListIndex::instanceDispose (no parent)");
|
||||
else {
|
||||
InteropException ie = new InteropException("Could not dispose ListIndex");
|
||||
GtkMain.schedule(() -> {
|
||||
try {
|
||||
var func = (MemoryAddress) ObjectClass.getMemoryLayout()
|
||||
.varHandle(MemoryLayout.PathElement.groupElement("dispose"))
|
||||
.get(MemorySegment.ofAddress(parentClass.handle().address(), ObjectClass.getMemoryLayout().byteSize(), Interop.getScope()));
|
||||
var linked = Linker.nativeLinker().downcallHandle(func, DisposeCallback.DESCRIPTOR);
|
||||
linked.invoke(pointer);
|
||||
} catch (Throwable e) {
|
||||
throw (InteropException) ie.initCause(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
private static final SetPropertyCallback setProperty = (object, propertyId, value, paramSpec) -> {
|
||||
if (propertyId != PROP_ITEM_TYPE) System.out.println("ListIndex::setProperty (unknown property)");
|
||||
};
|
||||
|
||||
private static final GetPropertyCallback getProperty = (object, propertyId, value, paramSpec) -> {
|
||||
if (propertyId == PROP_ITEM_TYPE) value.setGtype(getType());
|
||||
else System.out.println("ListIndex::getProperty (unknown property)");
|
||||
};
|
||||
|
||||
private static final ClassInitFunc classInit = (klass, data) -> {
|
||||
System.out.println("ListIndex::classInit");
|
||||
parentClass = klass.peekParent();
|
||||
ObjectClass objectClass = ObjectClass.fromAddress.marshal(GObject.typeCheckClassCast(klass, PARENT_TYPE).handle(), Ownership.NONE);
|
||||
objectClass.setDispose(instanceDispose.toCallback());
|
||||
objectClass.setGetProperty(getProperty.toCallback());
|
||||
objectClass.setSetProperty(setProperty.toCallback());
|
||||
|
||||
ParamSpec paramType = GObject.paramSpecGtype(PROP_NAME, "", "", PARENT_TYPE,
|
||||
ParamFlags.CONSTRUCT
|
||||
.or(ParamFlags.READWRITE,
|
||||
ParamFlags.STATIC_NAME,
|
||||
ParamFlags.STATIC_NICK,
|
||||
ParamFlags.STATIC_BLURB)
|
||||
);
|
||||
|
||||
objectClass.installProperty(PROP_ITEM_TYPE, paramType);
|
||||
};
|
||||
|
||||
private static final GetItemTypeCallback getItemType = address -> {
|
||||
System.out.println("ListIndex::getItemType");
|
||||
return getType().getValue();
|
||||
};
|
||||
private static final GetNItemsCallback getNItems = address -> fromAddress.marshal(address, Ownership.NONE).getSize();
|
||||
private static final GetItemCallback getItem = (inst, position) -> {
|
||||
ListIndex item = fromAddress.marshal(inst, Ownership.NONE).getItem(position);
|
||||
if (item == null) return MemoryAddress.NULL;
|
||||
return item.handle();
|
||||
};
|
||||
|
||||
public ListIndex getItem(int position) {
|
||||
if (position >= getSize() || position <= -1) return null;
|
||||
ListIndex result = new ListIndex(getSize());
|
||||
result.setIndex(position);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final InterfaceInitFunc interfaceInit = (iface, data) -> {
|
||||
System.out.println("ListIndex::interfaceInit");
|
||||
ListModelInterface lmi = ListModelInterface.fromAddress.marshal(iface.handle(), Ownership.NONE);
|
||||
lmi.setGetItem(getItem.toCallback());
|
||||
lmi.setGetNItems(getNItems.toCallback());
|
||||
lmi.setGetItemType(getItemType.toCallback());
|
||||
};
|
||||
|
||||
public int getIndex() {
|
||||
return (int) ListIndex.index.get(MemorySegment.ofAddress((MemoryAddress) handle(), memoryLayout.byteSize(), Interop.getScope()));
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
ListIndex.index.set(MemorySegment.ofAddress((MemoryAddress) handle(), memoryLayout.byteSize(), Interop.getScope()), index);
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return (int) ListIndex.size.get(MemorySegment.ofAddress((MemoryAddress) handle(), memoryLayout.byteSize(), Interop.getScope()));
|
||||
}
|
||||
|
||||
public void setSize(int size) {
|
||||
int oldSize = getSize();
|
||||
ListIndex.size.set(MemorySegment.ofAddress((MemoryAddress) handle(), memoryLayout.byteSize(), Interop.getScope()), size);
|
||||
asListModel().itemsChanged(0, oldSize, size);
|
||||
}
|
||||
|
||||
public ListModel asListModel() {
|
||||
return ListModel.castFrom(this);
|
||||
}
|
||||
|
||||
public SingleSelection inSingleSelection() {
|
||||
return new SingleSelection(asListModel());
|
||||
}
|
||||
|
||||
public SelectionModel inSelectionModel() {
|
||||
return SelectionModel.castFrom(inSingleSelection());
|
||||
}
|
||||
|
||||
public static int toIndex(ListItem item) {
|
||||
return castFrom(item.getItem()).getIndex();
|
||||
}
|
||||
}
|
|
@ -1,25 +1,24 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.window;
|
||||
|
||||
import ch.bailu.gtk.gtk.AboutDialog;
|
||||
import ch.bailu.gtk.gtk.License;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import org.gtk.gtk.AboutDialog;
|
||||
import org.gtk.gtk.License;
|
||||
import io.gitlab.jfronny.inceptum.common.BuildMetadata;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
||||
|
||||
public class AboutWindow extends AboutDialog {
|
||||
public AboutWindow() {
|
||||
setProgramName(new Str("Inceptum"));
|
||||
setCopyright(new Str("Copyright (C) 2021 JFronny"));
|
||||
setVersion(new Str(BuildMetadata.VERSION));
|
||||
setLicenseType(License.MIT_X11);
|
||||
setLicense(I18n.str("about.license"));
|
||||
setWebsiteLabel(I18n.str("about.contact"));
|
||||
setWebsite(new Str("https://jfronny.gitlab.io/contact.html"));
|
||||
programName = "Inceptum";
|
||||
copyright = "Copyright (C) 2021 JFronny";
|
||||
version = BuildMetadata.VERSION;
|
||||
licenseType = License.MIT_X11;
|
||||
license = I18n.get("about.license");
|
||||
websiteLabel = I18n.get("about.contact");
|
||||
website = "https://jfronny.gitlab.io/contact.html";
|
||||
if (!BuildMetadata.IS_PUBLIC) {
|
||||
setComments(I18n.str("about.unsupported-build"));
|
||||
comments = I18n.get("about.unsupported-build");
|
||||
}
|
||||
int vm = Runtime.version().feature();
|
||||
setSystemInformation(I18n.str(BuildMetadata.VM_VERSION == vm ? "about.jvm" : "about.jvm.unsupported", vm));
|
||||
systemInformation = I18n.get(BuildMetadata.VM_VERSION == vm ? "about.jvm" : "about.jvm.unsupported", vm);
|
||||
//TODO setLogo
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package io.gitlab.jfronny.inceptum.gtk.window;
|
||||
|
||||
import ch.bailu.gtk.GTK;
|
||||
import ch.bailu.gtk.adw.Clamp;
|
||||
import ch.bailu.gtk.adw.StatusPage;
|
||||
import ch.bailu.gtk.bridge.ListIndex;
|
||||
import ch.bailu.gtk.gio.Menu;
|
||||
import ch.bailu.gtk.glib.Glib;
|
||||
import ch.bailu.gtk.gtk.*;
|
||||
import ch.bailu.gtk.type.Str;
|
||||
import io.gitlab.jfronny.inceptum.gtk.util.ListIndex;
|
||||
import org.gnome.adw.Clamp;
|
||||
import org.gnome.adw.StatusPage;
|
||||
import org.gtk.gio.Menu;
|
||||
import org.gtk.glib.GLib;
|
||||
import org.gtk.gtk.*;
|
||||
import io.gitlab.jfronny.inceptum.common.*;
|
||||
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
|
||||
import io.gitlab.jfronny.inceptum.gtk.control.InstanceGridEntryFactory;
|
||||
|
@ -40,24 +38,24 @@ public class MainWindow extends ApplicationWindow {
|
|||
|
||||
HeaderBar header = new HeaderBar();
|
||||
Button newButton = new Button();
|
||||
newButton.setIconName(new Str("list-add-symbolic"));
|
||||
newButton.onClicked(NewInstanceWindow::createAndShow);
|
||||
newButton.setIconName("list-add-symbolic");
|
||||
newButton.onClicked($ -> NewInstanceWindow.createAndShow());
|
||||
|
||||
MenuButton accountsButton = new MenuButton();
|
||||
accountsButton.setIconName(new Str("avatar-default-symbolic"));
|
||||
accountsButton.setIconName("avatar-default-symbolic");
|
||||
accountsButton.setPopover(GtkMenubar.accountsMenu.asPopover());
|
||||
|
||||
listButton = new Button();
|
||||
listButton.setIconName(new Str("view-list-symbolic"));
|
||||
listButton.onClicked(() -> {
|
||||
listButton.setIconName("view-list-symbolic");
|
||||
listButton.onClicked($ -> {
|
||||
InceptumConfig.listView = true;
|
||||
InceptumConfig.saveConfig();
|
||||
generateWindowBody();
|
||||
});
|
||||
|
||||
gridButton = new Button();
|
||||
gridButton.setIconName(new Str("view-grid-symbolic"));
|
||||
gridButton.onClicked(() -> {
|
||||
gridButton.setIconName("view-grid-symbolic");
|
||||
gridButton.onClicked($ -> {
|
||||
InceptumConfig.listView = false;
|
||||
InceptumConfig.saveConfig();
|
||||
generateWindowBody();
|
||||
|
@ -70,7 +68,7 @@ public class MainWindow extends ApplicationWindow {
|
|||
uiMenu.button("preferences", () -> {}); //TODO preferences UI inspired by boxes
|
||||
uiMenu.button("about", AboutWindow::createAndShow);
|
||||
MenuButton menuButton = new MenuButton();
|
||||
menuButton.setIconName(new Str("open-menu-symbolic"));
|
||||
menuButton.setIconName("open-menu-symbolic");
|
||||
menuButton.setPopover(uiMenu.asPopover());
|
||||
|
||||
header.packStart(newButton);
|
||||
|
@ -84,26 +82,27 @@ public class MainWindow extends ApplicationWindow {
|
|||
instanceListIndex = new ListIndex();
|
||||
|
||||
listView = new Clamp();
|
||||
listView.setMaximumSize(900);
|
||||
listView.setChild(new ListView(instanceListIndex.inSelectionModel(), new InstanceListEntryFactory(instanceList)));
|
||||
listView.maximumSize = 900;
|
||||
listView.child = new ListView(instanceListIndex.inSelectionModel(), new InstanceListEntryFactory(instanceList));
|
||||
gridView = new GridView(instanceListIndex.inSelectionModel(), new InstanceGridEntryFactory(instanceList));
|
||||
empty = new StatusPage();
|
||||
empty.setTitle(I18n.str("main.empty.title"));
|
||||
empty.setDescription(I18n.str("main.empty.description"));
|
||||
empty.title = I18n.get("main.empty.title");
|
||||
empty.description = I18n.get("main.empty.description");
|
||||
//TODO empty.setIconName(new Str());
|
||||
stack = new Stack();
|
||||
stack.addChild(listView);
|
||||
stack.addChild(gridView);
|
||||
stack.addChild(empty);
|
||||
|
||||
ScrolledWindow scroll = new ScrolledWindow();
|
||||
scroll.setPolicy(PolicyType.NEVER, PolicyType.AUTOMATIC);
|
||||
scroll.setChild(stack);
|
||||
scroll.child = stack;
|
||||
|
||||
setDefaultSize(360, 720);
|
||||
setTitle(new Str("Inceptum"));
|
||||
setTitlebar(header);
|
||||
setShowMenubar(GTK.FALSE);
|
||||
setChild(scroll);
|
||||
title = "Inceptum";
|
||||
titlebar = header;
|
||||
showMenubar = false;
|
||||
child = scroll;
|
||||
|
||||
generateWindowBody();
|
||||
//TODO DropTarget to add mods/instances
|
||||
|
@ -118,7 +117,7 @@ public class MainWindow extends ApplicationWindow {
|
|||
private void setupDirWatcher() throws IOException { //TODO test (including after lock state change)
|
||||
WatchService ws = FileSystems.getDefault().newWatchService();
|
||||
MetaHolder.INSTANCE_DIR.register(ws, ENTRY_MODIFY, ENTRY_CREATE, ENTRY_DELETE);
|
||||
int source = Glib.idleAdd(user_data -> {
|
||||
int source = GLib.idleAdd(data -> {
|
||||
//TODO watch instance dirs for locks
|
||||
WatchKey key = ws.poll();
|
||||
boolean instancesChanged = false;
|
||||
|
@ -131,29 +130,29 @@ public class MainWindow extends ApplicationWindow {
|
|||
}
|
||||
}
|
||||
if (instancesChanged) generateWindowBody();
|
||||
return GTK.TRUE;
|
||||
return true;
|
||||
}, null);
|
||||
onCloseRequest(() -> {
|
||||
onCloseRequest($ -> {
|
||||
try {
|
||||
ws.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
Glib.sourceRemove(source);
|
||||
return GTK.FALSE;
|
||||
GLib.sourceRemove(source);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private void generateWindowBody() {
|
||||
if (listButton != null) listButton.setVisible(GTK.is(!InceptumConfig.listView));
|
||||
if (gridButton != null) gridButton.setVisible(GTK.is(InceptumConfig.listView));
|
||||
if (listButton != null) listButton.visible = !InceptumConfig.listView;
|
||||
if (gridButton != null) gridButton.visible = InceptumConfig.listView;
|
||||
try {
|
||||
instanceList.clear();
|
||||
instanceList.addAll(InstanceList.ordered());
|
||||
instanceListIndex.setSize(instanceList.size());
|
||||
|
||||
if (InstanceList.isEmpty()) stack.setVisibleChild(empty);
|
||||
else if (InceptumConfig.listView) stack.setVisibleChild(listView);
|
||||
else stack.setVisibleChild(gridView);
|
||||
if (InstanceList.isEmpty) stack.visibleChild = empty;
|
||||
else if (InceptumConfig.listView) stack.visibleChild = listView;
|
||||
else stack.visibleChild = gridView;
|
||||
} catch (IOException e) {
|
||||
Utils.LOGGER.error("Could not generate window body", e);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,6 @@ instance.launch.locked.running=This instance is currently running.\
|
|||
Click OK to start a second instance of the game.\
|
||||
Please be aware that doing so is unsupported and WILL cause issues!
|
||||
instance.launch=Launch
|
||||
main.empty.title=# Welcome to Inceptum
|
||||
main.empty.title=Welcome to Inceptum
|
||||
main.empty.description=To get started, create (or import) a new instance using the + button
|
||||
instance.directory=Open Directory
|
||||
|
|
|
@ -28,6 +28,6 @@ instance.launch.locked.running=Diese Instanz l
|
|||
Bestätigen sie den Start mit OK, um sie ein zweites mal zu starten.\
|
||||
Bitte seien sie sich bewusst, dass dies zu Problemen führen wird und NICHT UNTERSÜTZT ist.
|
||||
instance.launch=Starten
|
||||
main.empty.title=# Willkommen bei Inceptum
|
||||
main.empty.title=Willkommen bei Inceptum
|
||||
main.empty.description=Importiere oder erstelle um anzufangen eine Instanz mit dem +
|
||||
instance.directory=Verzeichnis öffnen
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.application-conventions")
|
||||
id("inceptum.application")
|
||||
id("inceptum.manifold")
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("inceptum.library")
|
||||
id("inceptum.gson-compile")
|
||||
id("inceptum.manifold")
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
|
|||
import java.io.IOException;
|
||||
|
||||
public class MicrosoftAccountAdapter {
|
||||
public static void write(JsonWriter writer, MicrosoftAccount value) throws IOException {
|
||||
public static void write(MicrosoftAccount value, JsonWriter writer) throws IOException {
|
||||
GC_MicrosoftAccountMeta.write(value == null ? null : value.toMeta(), writer);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
public class MinecraftArgumentAdapter {
|
||||
public static void write(JsonWriter writer, MinecraftArgument rules) throws IOException {
|
||||
public static void write(MinecraftArgument rules, JsonWriter writer) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,22 +3,22 @@ package io.gitlab.jfronny.inceptum.launcher.gson;
|
|||
import gsoncompile.extensions.io.gitlab.jfronny.inceptum.launcher.system.source.ModSource.GC_ModSource;
|
||||
import io.gitlab.jfronny.gson.stream.JsonReader;
|
||||
import io.gitlab.jfronny.gson.stream.JsonWriter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta$Sources;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta.Sources;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ModMetaSourcesAdapter {
|
||||
public static void write(JsonWriter writer, ModMeta$Sources value) throws IOException {
|
||||
public static void write(Sources value, JsonWriter writer) throws IOException {
|
||||
writer.beginArray();
|
||||
for (ModSource source : value.keySet()) GC_ModSource.write(source, writer);
|
||||
writer.endArray();
|
||||
}
|
||||
|
||||
public static ModMeta$Sources read(JsonReader reader) throws IOException {
|
||||
public static Sources read(JsonReader reader) throws IOException {
|
||||
reader.beginArray();
|
||||
ModMeta$Sources sources = new ModMeta$Sources();
|
||||
Sources sources = new Sources();
|
||||
while (reader.hasNext()) {
|
||||
sources.put(GC_ModSource.read(reader), Optional.empty());
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import java.util.LinkedHashSet;
|
|||
import java.util.Set;
|
||||
|
||||
public class ModSourceAdapter {
|
||||
public static void write(JsonWriter writer, ModSource src) throws IOException {
|
||||
public static void write(ModSource src, JsonWriter writer) throws IOException {
|
||||
writer.beginObject();
|
||||
if (src instanceof ModrinthModSource mo) {
|
||||
writer.name("type").value("modrinth")
|
||||
|
@ -22,7 +22,7 @@ public class ModSourceAdapter {
|
|||
.name("dependencies");
|
||||
writer.beginArray();
|
||||
for (ModSource dependency : di.dependencies) {
|
||||
write(writer, dependency);
|
||||
write(dependency, writer);
|
||||
}
|
||||
writer.endArray();
|
||||
} else if (src instanceof CurseforgeModSource cu) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import io.gitlab.jfronny.inceptum.launcher.model.mojang.Rules;
|
|||
import java.io.IOException;
|
||||
|
||||
public class RulesAdapter {
|
||||
public static void write(JsonWriter writer, Rules rules) throws IOException {
|
||||
public static void write(Rules rules, JsonWriter writer) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,79 +0,0 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.common.GsonPreset;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.ModMetaSourcesAdapter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@GSerializable(with = ModMetaSourcesAdapter.class, configure = GsonPreset.Config.class)
|
||||
public class ModMeta$Sources implements Map<ModSource, Optional<ModSource>> {
|
||||
private Map<ModSource, Optional<ModSource>> delegate = new LinkedHashMap<>();
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return delegate.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return delegate.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object o) {
|
||||
return delegate.containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object o) {
|
||||
return delegate.containsValue(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModSource> get(Object o) {
|
||||
return delegate[o];
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Optional<ModSource> put(ModSource modSource, Optional<ModSource> modSource2) {
|
||||
return delegate.put(modSource, modSource2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<ModSource> remove(Object o) {
|
||||
return delegate.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putAll(@NotNull Map<? extends ModSource, ? extends Optional<ModSource>> map) {
|
||||
delegate.putAll(map);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
delegate.clear();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<ModSource> keySet() {
|
||||
return delegate.keySet();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Optional<ModSource>> values() {
|
||||
return delegate.values();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<ModSource, Optional<ModSource>>> entrySet() {
|
||||
return delegate.entrySet();
|
||||
}
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
package io.gitlab.jfronny.inceptum.launcher.model.inceptum;
|
||||
|
||||
import io.gitlab.jfronny.commons.HashUtils;
|
||||
import io.gitlab.jfronny.commons.data.MutCollection;
|
||||
import io.gitlab.jfronny.commons.data.delegate.DelegateMap;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GPrefer;
|
||||
import io.gitlab.jfronny.gson.compile.annotations.GSerializable;
|
||||
import io.gitlab.jfronny.inceptum.common.GsonPreset;
|
||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.CurseforgeApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.api.ModrinthApi;
|
||||
import io.gitlab.jfronny.inceptum.launcher.gson.ModMetaSourcesAdapter;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.curseforge.response.FingerprintMatchesResponse;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.*;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.CurseforgeModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModSource;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.source.ModrinthModSource;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -17,16 +22,24 @@ import java.nio.file.Files;
|
|||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@GSerializable(configure = GsonPreset.Config.class)
|
||||
public record ModMeta(
|
||||
ModMeta$Sources sources, //key: source, value: update
|
||||
Sources sources, //key: source, value: update
|
||||
String sha1,
|
||||
Long murmur2,
|
||||
List<String> dependents, // by file name
|
||||
List<String> dependencies, // by file name
|
||||
boolean explicit
|
||||
) {
|
||||
@GSerializable(with = ModMetaSourcesAdapter.class, configure = GsonPreset.Config.class)
|
||||
public static class Sources extends DelegateMap<ModSource, Optional<ModSource>> {
|
||||
public Sources() {
|
||||
super(MutCollection.mapOf());
|
||||
}
|
||||
}
|
||||
|
||||
@GPrefer
|
||||
public ModMeta {}
|
||||
|
||||
|
@ -43,7 +56,7 @@ public record ModMeta(
|
|||
}
|
||||
}
|
||||
return new ModMeta(
|
||||
new ModMeta$Sources(),
|
||||
new Sources(),
|
||||
sha1,
|
||||
murmur2,
|
||||
new ArrayList<>(),
|
||||
|
@ -54,7 +67,7 @@ public record ModMeta(
|
|||
|
||||
public static ModMeta of(String sha1, Long murmur2, @Nullable ModSource knownSource, String gameVersion) {
|
||||
ModMeta res = new ModMeta(
|
||||
new ModMeta$Sources(),
|
||||
new Sources(),
|
||||
sha1,
|
||||
murmur2,
|
||||
new ArrayList<>(),
|
||||
|
|
|
@ -19,7 +19,7 @@ public class InstanceList {
|
|||
|
||||
public static void reset() {
|
||||
synchronized (metas) {
|
||||
for (var entry : metas) {
|
||||
for (var entry : metas.entrySet()) {
|
||||
try {
|
||||
entry.value.close();
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import io.gitlab.jfronny.gson.JsonParseException;
|
|||
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.fabric.FabricModJson;
|
||||
import io.gitlab.jfronny.inceptum.launcher.model.inceptum.ModMeta;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Mod;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.ModPath;
|
||||
import io.gitlab.jfronny.inceptum.launcher.system.mds.noop.NoopMod;
|
||||
|
@ -26,75 +27,53 @@ public record FileScanTask(ProtoInstance instance, Path file, BiConsumer<Path, M
|
|||
if (!Files.exists(file)) return;
|
||||
if (Files.isDirectory(file)) return; // Directories are not supported
|
||||
try {
|
||||
if (ModPath.isJar(file)) {
|
||||
final MetadataRef imod = new MetadataRef(file.parent.resolve(file.fileName + ModPath.EXT_IMOD), ModMeta::of);
|
||||
evaluateSources(file, imod);
|
||||
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, file, false, imod.meta, getFmj(file, imod.meta)));
|
||||
} else if (ModPath.isImod(file)) {
|
||||
String fn = file.fileName.toString();
|
||||
Path modFile = file.parent.resolve(fn.substring(0, fn.length() - ModPath.EXT_IMOD.length()));
|
||||
final MetadataRef imod = new MetadataRef(file, null);
|
||||
evaluateSources(modFile, imod);
|
||||
boolean managedJar = !Files.exists(modFile);
|
||||
discovered.accept(imod.imodPath, new MdsMod(instance, imod.imodPath, managedJar ? imod.jarPath : modFile, managedJar, imod.meta, getFmj(modFile, imod.meta)));
|
||||
} else discovered.accept(file, new NoopMod(file));
|
||||
if (ModPath.isJar(file)) discover(file, ModPath.appendImod(file));
|
||||
else if (ModPath.isImod(file)) discover(ModPath.trimImod(file), file);
|
||||
else discovered.accept(file, new NoopMod(file));
|
||||
} catch (IOException | URISyntaxException | JsonParseException e) {
|
||||
Utils.LOGGER.error("Could not scan file for mod info", e);
|
||||
}
|
||||
}
|
||||
|
||||
private <TEx extends Throwable> void evaluateSources(Path modFile, MetadataRef ref) throws IOException, TEx {
|
||||
private void discover(Path jarPath, Path imodPath) throws IOException, URISyntaxException {
|
||||
boolean managed = false;
|
||||
ModMeta meta;
|
||||
if (Files.exists(imodPath)) meta = GC_ModMeta.read(imodPath);
|
||||
else {
|
||||
meta = ModMeta.of(jarPath);
|
||||
GC_ModMeta.write(meta, imodPath);
|
||||
}
|
||||
boolean modified = false;
|
||||
if (ref.meta.initialize(gameVersion)) {
|
||||
GC_ModMeta.write(ref.meta, ref.imodPath);
|
||||
if (meta.initialize(gameVersion)) {
|
||||
GC_ModMeta.write(meta, imodPath);
|
||||
modified = true;
|
||||
}
|
||||
ModSource selectedSource = null;
|
||||
for (ModSource source : ref.meta.sources.keySet()) {
|
||||
for (ModSource source : meta.sources.keySet()) {
|
||||
source.getUpdate(gameVersion);
|
||||
if (!Files.exists(source.jarPath)) source.download();
|
||||
selectedSource = source;
|
||||
}
|
||||
if (selectedSource != null) {
|
||||
if (Files.exists(modFile)) {
|
||||
Files.delete(modFile);
|
||||
Path newImod = ref.imodPath.parent.resolve(selectedSource.shortName + ModPath.EXT_IMOD);
|
||||
Files.move(ref.imodPath, newImod);
|
||||
ref.imodPath = newImod;
|
||||
if (Files.exists(jarPath)) {
|
||||
Files.delete(jarPath);
|
||||
Path newImod = imodPath.parent.resolve(selectedSource.shortName + ModPath.EXT_IMOD);
|
||||
Files.move(imodPath, newImod);
|
||||
imodPath = newImod;
|
||||
modified = true;
|
||||
}
|
||||
ref.jarPath = selectedSource.jarPath;
|
||||
}
|
||||
if (modified) ref.update();
|
||||
}
|
||||
jarPath = selectedSource.jarPath;
|
||||
managed = true;
|
||||
} else if (!Files.exists(jarPath)) throw new IOException("Mod has no jar and no sources");
|
||||
if (modified) meta = GC_ModMeta.read(imodPath);
|
||||
|
||||
private @Nullable FabricModJson getFmj(Path modJarDefault, ModMeta md) throws IOException, URISyntaxException {
|
||||
if (!Files.exists(modJarDefault)) {
|
||||
if (md.sources.isEmpty()) {
|
||||
throw new FileNotFoundException("Mod " + modJarDefault.fileName.toString() + " doesn't specify a source and has no file");
|
||||
}
|
||||
modJarDefault = List.copyOf(md.sources.keySet())[0].jarPath;
|
||||
}
|
||||
try (FileSystem fs = Utils.openZipFile(modJarDefault, false)) {
|
||||
FabricModJson fmj;
|
||||
try (FileSystem fs = Utils.openZipFile(jarPath, false)) {
|
||||
Path fmjPath = fs.getPath("fabric.mod.json");
|
||||
if (!Files.exists(fmjPath)) return null;
|
||||
return GC_FabricModJson.read(fmjPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static class MetadataRef {
|
||||
public MetadataRef(Path imodPath, @Nullable Function<Path, ModMeta> defaultMeta) throws IOException {
|
||||
this.imodPath = imodPath;
|
||||
if (!Files.exists(imodPath) && defaultMeta != null) GC_ModMeta.write(defaultMeta.apply(imodPath), imodPath);
|
||||
if (Files.exists(imodPath)) update();
|
||||
if (Files.exists(fmjPath)) fmj = GC_FabricModJson.read(fmjPath);
|
||||
else fmj = null;
|
||||
}
|
||||
|
||||
public Path imodPath;
|
||||
public Path jarPath; // filled in from evaluateSources
|
||||
public ModMeta meta;
|
||||
|
||||
public void update() throws IOException {
|
||||
this.meta = GC_ModMeta.read(imodPath);
|
||||
}
|
||||
discovered.accept(imodPath, new MdsMod(instance, imodPath, jarPath, managed, meta, fmj));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -131,8 +131,7 @@ class ModsDirScannerImpl implements ModsDirScanner {
|
|||
if (!key.reset()) Utils.LOGGER.warn("Could not reset config watch key");
|
||||
}
|
||||
JFiles.listTo(instance.modsDir, path -> {
|
||||
if (!descriptions.containsKey(path))
|
||||
toScan.add(path);
|
||||
if (!descriptions.containsKey(path)) toScan.add(path);
|
||||
});
|
||||
}
|
||||
for (Path p : toScan) {
|
||||
|
|
|
@ -27,7 +27,7 @@ public class DownloadAssetsStep implements Step {
|
|||
info.setState("Downloading asset: " + entry.key);
|
||||
McApi.downloadAsset(entry.value, fPath);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
} catch (Throwable e) {
|
||||
throw new IOException("Could not download assets", e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ import java.io.InputStreamReader;
|
|||
|
||||
public class ProcessUtils {
|
||||
public static boolean isProcessAlive(String pid) {
|
||||
return isProcessIdRunning(pid, OSUtils.TYPE == OSUtils.Type.WINDOWS
|
||||
? "cmd /c tasklist /FI \"PID eq " + pid + "\""
|
||||
: "ps -p " + pid);
|
||||
if (OSUtils.TYPE == OSUtils.Type.WINDOWS)
|
||||
return isProcessIdRunning(pid, "tasklist", "/FI", "PID eq " + pid);
|
||||
return isProcessIdRunning(pid, "ps", "-p", pid);
|
||||
}
|
||||
|
||||
private static boolean isProcessIdRunning(String pid, String command) {
|
||||
private static boolean isProcessIdRunning(String pid, String... command) {
|
||||
try {
|
||||
Runtime rt = Runtime.getRuntime();
|
||||
Process pr = rt.exec(command);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.library-conventions")
|
||||
id("inceptum.library")
|
||||
}
|
||||
|
||||
java {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 11fb5ad2ad266bac007e7b11178fc3585cac45b9
|
||||
Subproject commit 28770e5269128412d8d51a03aa6c072a8eff10cb
|
|
@ -1,5 +1,5 @@
|
|||
plugins {
|
||||
id("inceptum.application-standalone-conventions")
|
||||
id("inceptum.application-standalone")
|
||||
}
|
||||
|
||||
application {
|
||||
|
|
Loading…
Reference in New Issue