2022-09-30 18:07:18 +02:00
|
|
|
package io.gitlab.jfronny.inceptum.gtk.control;
|
|
|
|
|
2023-01-13 19:34:29 +01:00
|
|
|
import io.github.jwharm.javagi.Signal;
|
|
|
|
import io.gitlab.jfronny.commons.io.JFiles;
|
|
|
|
import io.gitlab.jfronny.commons.ref.R;
|
|
|
|
import io.gitlab.jfronny.inceptum.common.MetaHolder;
|
2022-09-30 18:07:18 +02:00
|
|
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
|
|
|
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
|
2023-01-13 19:34:29 +01:00
|
|
|
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder;
|
2022-09-30 18:07:18 +02:00
|
|
|
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
|
2023-01-13 19:34:29 +01:00
|
|
|
import io.gitlab.jfronny.inceptum.gtk.util.ListIndexItem;
|
|
|
|
import io.gitlab.jfronny.inceptum.launcher.LauncherEnv;
|
|
|
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.*;
|
|
|
|
import io.gitlab.jfronny.inceptum.launcher.system.launch.LaunchType;
|
|
|
|
import org.gnome.adw.ActionRow;
|
|
|
|
import org.gtk.gio.ActionMap;
|
|
|
|
import org.gtk.gio.Menu;
|
|
|
|
import org.gtk.gtk.Stack;
|
|
|
|
import org.gtk.gtk.*;
|
2022-09-30 18:07:18 +02:00
|
|
|
|
2023-01-13 19:34:29 +01:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.nio.file.Files;
|
|
|
|
import java.util.*;
|
|
|
|
import java.util.function.Consumer;
|
2022-09-30 18:07:18 +02:00
|
|
|
|
|
|
|
public class InstanceListEntryFactory extends SignalListItemFactory {
|
2023-01-13 19:34:29 +01:00
|
|
|
public InstanceListEntryFactory(List<Instance> instanceList, ActionMap actionMap) {
|
2022-09-30 18:07:18 +02:00
|
|
|
super();
|
2023-01-10 21:20:01 +01:00
|
|
|
onSetup(item -> {
|
2022-09-30 18:07:18 +02:00
|
|
|
var thumbnail = new InstanceThumbnail();
|
2022-12-17 21:53:21 +01:00
|
|
|
thumbnail.name = "inceptum-thumbnail";
|
2022-09-30 18:07:18 +02:00
|
|
|
|
|
|
|
var launch = new Button();
|
2023-01-13 19:34:29 +01:00
|
|
|
launch.addCssClass("flat");
|
2022-12-17 21:53:21 +01:00
|
|
|
launch.name = "inceptum-launch";
|
2023-01-13 19:34:29 +01:00
|
|
|
launch.iconName = "media-playback-start-symbolic";
|
2022-12-17 21:53:21 +01:00
|
|
|
launch.tooltipText = I18n.get("instance.launch");
|
|
|
|
launch.hasTooltip = true;
|
2022-09-30 18:07:18 +02:00
|
|
|
|
2023-01-13 19:34:29 +01:00
|
|
|
var menu = new MenuButton();
|
|
|
|
menu.addCssClass("flat");
|
|
|
|
menu.iconName = "view-more-symbolic";
|
|
|
|
menu.menuModel = new Menu();
|
2022-09-30 18:07:18 +02:00
|
|
|
|
2022-10-19 20:28:49 +02:00
|
|
|
var row = new ActionRow();
|
2023-01-13 19:34:29 +01:00
|
|
|
row.margin = 8;
|
2022-12-17 21:53:21 +01:00
|
|
|
row.name = "inceptum-row";
|
|
|
|
row.activatableWidget = launch;
|
2022-10-19 20:28:49 +02:00
|
|
|
row.addPrefix(thumbnail);
|
|
|
|
row.addSuffix(launch);
|
2023-01-13 19:34:29 +01:00
|
|
|
row.addSuffix(menu);
|
|
|
|
|
|
|
|
var clicked = new GestureClick();
|
|
|
|
clicked.onPressed((nPress, x, y) -> {
|
|
|
|
if (nPress == 2) launch.emitClicked(launch);
|
|
|
|
});
|
|
|
|
row.addController(clicked);
|
|
|
|
var rightClicked = new GestureClick();
|
|
|
|
rightClicked.button = 3;
|
|
|
|
rightClicked.onPressed((nPress, x, y) -> {
|
|
|
|
if (nPress == 1) menu.emitActivate(menu);
|
|
|
|
});
|
|
|
|
row.addController(rightClicked);
|
2022-09-30 18:07:18 +02:00
|
|
|
|
2023-01-10 21:20:01 +01:00
|
|
|
((ListItem) item).setChild(row);
|
2022-09-30 18:07:18 +02:00
|
|
|
|
|
|
|
});
|
2023-01-13 19:34:29 +01:00
|
|
|
Map<String, Set<Signal<?>>> toDisconnect = new HashMap<>();
|
|
|
|
|
2023-01-10 21:20:01 +01:00
|
|
|
onBind(item -> {
|
2023-01-13 19:34:29 +01:00
|
|
|
Decomposed li = Decomposed.of((ListItem) item, instanceList);
|
|
|
|
li.row.title = li.instance.toString();
|
|
|
|
|
|
|
|
li.thumbnail.bind(li.instance);
|
2022-10-19 20:28:49 +02:00
|
|
|
|
2023-01-13 19:34:29 +01:00
|
|
|
//TODO fix menu not interactable
|
|
|
|
var menuBuilder = new MenuBuilder(actionMap, li.menu, li.instance.id);
|
|
|
|
var launchSection = menuBuilder.literalSection("launch", null);
|
|
|
|
launchSection.literalButton("launch.client", I18n.get("instance.launch.client"),
|
|
|
|
() -> GtkMenubar.launch(li.instance, LaunchType.Client))
|
|
|
|
.iconName = "media-playback-start-symbolic";
|
|
|
|
launchSection.literalButton("launch.server", I18n.get("instance.launch.server"),
|
|
|
|
() -> GtkMenubar.launch(li.instance, LaunchType.Server))
|
|
|
|
.iconName = "network-server-symbolic";
|
|
|
|
var settingsSection = menuBuilder.literalSection("settings", null);
|
|
|
|
settingsSection.literalButton("settings", I18n.get("instance.settings"), () -> {
|
|
|
|
//TODO open settings
|
|
|
|
}).iconName = "document-edit-symbolic";
|
|
|
|
settingsSection.literalButton("directory", I18n.get("instance.directory"),
|
|
|
|
() -> Utils.openFile(li.instance.path.toFile()))
|
|
|
|
.iconName = "folder-symbolic";
|
|
|
|
settingsSection.literalButton("copy", I18n.get("instance.copy"), () -> {
|
|
|
|
LauncherEnv.getInput(I18n.get("instance.copy.prompt"), I18n.get("instance.copy.details"), InstanceNameTool.getNextValid(li.instance.name), s -> {
|
|
|
|
try {
|
|
|
|
JFiles.copyRecursive(li.instance.path, MetaHolder.INSTANCE_DIR.resolve(InstanceNameTool.getNextValid(s)));
|
|
|
|
} catch (IOException e) {
|
|
|
|
LauncherEnv.showError("Could not copy instance", e);
|
|
|
|
}
|
|
|
|
}, R::nop);
|
|
|
|
}).iconName = "edit-copy-symbolic";
|
|
|
|
settingsSection.literalButton("delete", I18n.get("instance.delete"), () -> {
|
|
|
|
LauncherEnv.showOkCancel("This instance will be removed forever (a long time)", "Are you sure?", () -> {
|
|
|
|
try {
|
|
|
|
JFiles.deleteRecursive(li.instance.path);
|
|
|
|
} catch (IOException e) {
|
|
|
|
LauncherEnv.showError("Could not delete the instance", e);
|
|
|
|
}
|
|
|
|
}, R::nop);
|
|
|
|
}).iconName = "edit-delete-symbolic";
|
|
|
|
|
|
|
|
//TODO kill current instance
|
|
|
|
|
|
|
|
Consumer<Signal<?>> dc = s -> toDisconnect.computeIfAbsent(li.instance.id, $ -> new HashSet<>()).add(s);
|
|
|
|
|
|
|
|
dc.accept(li.launch.onClicked(() -> GtkMenubar.launch(li.instance, LaunchType.Client)));
|
|
|
|
});
|
|
|
|
onUnbind(item -> {
|
|
|
|
Decomposed li = Decomposed.of((ListItem) item, instanceList);
|
|
|
|
li.menu.removeAll();
|
|
|
|
toDisconnect.get(li.instance.id).forEach(Signal::disconnect);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
private record Decomposed(Instance instance, ActionRow row, InstanceThumbnail thumbnail, Button launch, Menu menu) {
|
|
|
|
public static Decomposed of(ListItem item, List<Instance> instanceList) {
|
|
|
|
Instance instance = instanceList.get(((ListIndexItem) item.getItem()).getIntValue());
|
|
|
|
ActionRow row = (ActionRow) item.child;
|
2023-01-10 21:20:01 +01:00
|
|
|
Box prefixes = (Box) row.firstChild.firstChild;
|
|
|
|
Box suffixes = (Box) row.firstChild.lastChild;
|
|
|
|
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom((Stack) prefixes.firstChild);
|
|
|
|
Button launch = (Button) suffixes.firstChild;
|
2023-01-13 19:34:29 +01:00
|
|
|
MenuButton menuButton = (MenuButton) launch.nextSibling;
|
|
|
|
return new Decomposed(instance, row, thumbnail, launch, (Menu) menuButton.menuModel);
|
|
|
|
}
|
2022-09-30 18:07:18 +02:00
|
|
|
}
|
|
|
|
}
|