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

137 lines
6.2 KiB
Java

package io.gitlab.jfronny.inceptum.gtk.control;
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;
import io.gitlab.jfronny.inceptum.common.Utils;
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder;
import io.gitlab.jfronny.inceptum.gtk.util.I18n;
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.*;
import java.io.IOException;
import java.nio.file.Files;
import java.util.*;
import java.util.function.Consumer;
public class InstanceListEntryFactory extends SignalListItemFactory {
public InstanceListEntryFactory(List<Instance> instanceList, ActionMap actionMap) {
super();
onSetup(item -> {
var thumbnail = new InstanceThumbnail();
thumbnail.name = "inceptum-thumbnail";
var launch = new Button();
launch.addCssClass("flat");
launch.name = "inceptum-launch";
launch.iconName = "media-playback-start-symbolic";
launch.tooltipText = I18n.get("instance.launch");
launch.hasTooltip = true;
var menu = new MenuButton();
menu.addCssClass("flat");
menu.iconName = "view-more-symbolic";
menu.menuModel = new Menu();
var row = new ActionRow();
row.margin = 8;
row.name = "inceptum-row";
row.activatableWidget = launch;
row.addPrefix(thumbnail);
row.addSuffix(launch);
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);
((ListItem) item).setChild(row);
});
Map<String, Set<Signal<?>>> toDisconnect = new HashMap<>();
onBind(item -> {
Decomposed li = Decomposed.of((ListItem) item, instanceList);
li.row.title = li.instance.toString();
li.thumbnail.bind(li.instance);
//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;
Box prefixes = (Box) row.firstChild.firstChild;
Box suffixes = (Box) row.firstChild.lastChild;
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom((Stack) prefixes.firstChild);
Button launch = (Button) suffixes.firstChild;
MenuButton menuButton = (MenuButton) launch.nextSibling;
return new Decomposed(instance, row, thumbnail, launch, (Menu) menuButton.menuModel);
}
}
}