Inceptum/launcher-gtk/src/main/java/io/gitlab/jfronny/inceptum/gtk/GtkMenubar.java

196 lines
8.8 KiB
Java

package io.gitlab.jfronny.inceptum.gtk;
import io.gitlab.jfronny.commons.io.JFiles;
import io.gitlab.jfronny.inceptum.common.MetaHolder;
import io.gitlab.jfronny.inceptum.gtk.window.dialog.MicrosoftLoginDialog;
import io.gitlab.jfronny.inceptum.gtk.window.dialog.ProcessStateWatcherDialog;
import io.gitlab.jfronny.inceptum.gtk.window.settings.launcher.LauncherSettingsWindow;
import io.gitlab.jfronny.inceptum.launcher.system.importer.Importers;
import io.gitlab.jfronny.inceptum.launcher.system.launch.*;
import io.gitlab.jfronny.inceptum.launcher.util.ProcessState;
import org.gtk.gio.Menu;
import org.gtk.gtk.*;
import io.gitlab.jfronny.commons.ref.R;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder;
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
import io.gitlab.jfronny.inceptum.gtk.window.AboutWindow;
import io.gitlab.jfronny.inceptum.gtk.window.NewInstanceWindow;
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.io.IOException;
import java.nio.file.Path;
import java.util.*;
import java.util.List;
public class GtkMenubar {
public static MenuBuilder newMenu;
public static MenuBuilder accountsMenu;
public static MenuBuilder launchMenu;
public static void create(Application app) {
var menu = new MenuBuilder(app);
var file = menu.submenu("file");
newMenu = file.submenu("new");
generateNewMenu(app);
file.button("redownload", () -> {
ProcessState state = new ProcessState(3 + Steps.STEPS.size() * InstanceList.size(), "Initializing");
ProcessStateWatcherDialog.show(
GtkEnvBackend.INSTANCE.dialogParent,
"Reloading data",
"Could not execute refresh task",
state,
() -> {
state.incrementStep("Clearing cache directories");
JFiles.clearDirectory(MetaHolder.ASSETS_DIR);
JFiles.clearDirectory(MetaHolder.LIBRARIES_DIR, path -> !path.startsWith(MetaHolder.LIBRARIES_DIR.resolve("io/gitlab/jfronny")));
JFiles.clearDirectory(MetaHolder.NATIVES_DIR, path -> !path.startsWith(MetaHolder.NATIVES_DIR.resolve("forceload")));
JFiles.clearDirectory(MetaHolder.CACHE_DIR);
if (state.isCancelled) return;
state.incrementStep("Reloading instance list");
InstanceList.reset();
InstanceList.forEach(instance -> {
if (state.isCancelled) return;
Steps.reDownload(instance, state);
});
});
});
file.button("exit", app::quit);
launchMenu = menu.submenu("launch");
generateLaunchMenu(app);
accountsMenu = menu.submenu("account");
generateAccountsMenu(app);
var help = menu.submenu("help");
help.button("about", AboutWindow::createAndShow);
help.button("log", () -> {
//TODO
});
}
public static void generateNewMenu(Application app) {
Objects.requireNonNull(newMenu).clear();
newMenu.button("new", () -> new NewInstanceWindow(app).show());
newMenu.button("file", () -> {
FileChooserNative dialog = new FileChooserNative(
I18n.get("menu.file.new.file"),
GtkEnvBackend.INSTANCE.dialogParent,
FileChooserAction.OPEN,
"_" + I18n.get("select"),
"_" + I18n.get("cancel")
);
var filter = new FileFilter();
filter.addPattern("*.zip");
filter.addPattern("*.mrpack");
dialog.addFilter(filter);
dialog.onResponse(responseId -> {
if (responseId == ResponseType.ACCEPT.value) {
var file = dialog.file.path;
if (file == null) {
LauncherEnv.showError("The path returned by the file dialog is null", "Could not import");
return;
}
ProcessState state = new ProcessState(Importers.MAX_STEPS, "Initializing");
ProcessStateWatcherDialog.show(
GtkEnvBackend.INSTANCE.dialogParent,
I18n.get("menu.file.new.file"),
I18n.get("menu.file.new.file.error"),
state,
() -> Importers.importPack(Path.of(file), state)
);
}
});
dialog.show();
});
newMenu.button("url", () -> {
LauncherEnv.getInput(
I18n.get("menu.file.new.url"),
I18n.get("menu.file.new.url.details"),
(String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor),
s -> {
ProcessState state = new ProcessState(Importers.MAX_STEPS, "Initializing");
ProcessStateWatcherDialog.show(
GtkEnvBackend.INSTANCE.dialogParent,
I18n.get("menu.file.new.url"),
I18n.get("menu.file.new.url.error"),
state,
() -> Importers.importPack(s, state)
);
},
R::nop
);
});
}
public static void generateLaunchMenu(Application app) {
Objects.requireNonNull(launchMenu).clear();
try {
InstanceList.forEach(entry -> {
launchMenu.literalButton(entry.id() + ".launch", entry.toString(), () -> launch(entry, LaunchType.Client));
});
} catch (IOException e) {
Utils.LOGGER.error("Could not generate launch menu", e);
}
}
public static void launch(Instance instance, LaunchType launchType) {
if (instance.isSetupLocked) {
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
} else if (instance.isRunningLocked) {
LauncherEnv.showOkCancel(
I18n.get("instance.launch.locked.running"),
I18n.get("instance.launch.locked"),
() -> forceLaunch(instance, launchType),
R::nop
);
} else forceLaunch(instance, launchType);
}
private static void forceLaunch(Instance instance, LaunchType launchType) {
ProcessState state = Steps.createProcessState();
ProcessStateWatcherDialog.show(
GtkEnvBackend.INSTANCE.dialogParent,
I18n.get("instance.launch.title"),
I18n.get("instance.launch.error"),
state,
() -> {
try {
Steps.reDownload(instance, state);
} catch (IOException e) {
Utils.LOGGER.error("Could not fetch instance, trying to start anyways", e);
}
if (state.isCancelled) return;
state.updateStep("Starting Game");
try {
if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance);
else InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH);
} catch (Throwable e) {
LauncherEnv.showError("Could not start instance", e);
}
}
);
}
public static void generateAccountsMenu(Application app) {
Objects.requireNonNull(accountsMenu).clear();
accountsMenu.button("new", () -> new MicrosoftLoginDialog(GtkEnvBackend.INSTANCE.dialogParent).show());
accountsMenu.button("manage", () -> {
var window = new LauncherSettingsWindow(app);
window.activePage = "settings.accounts";
window.show();
});
List<MicrosoftAccount> accounts = new ArrayList<>(AccountManager.accounts);
accounts.add(null);
accountsMenu.literalRadio("account", accounts.get(AccountManager.selectedIndex), accounts, (i, acc) -> {
if (acc == null) return I18n.get("account.none");
return acc.minecraftUsername;
}, AccountManager::switchAccount);
}
}