Tweak main window
This commit is contained in:
parent
d4a016771f
commit
c52f1f3350
|
@ -3,14 +3,14 @@
|
||||||
|
|
||||||
pipeline:
|
pipeline:
|
||||||
export_metadata:
|
export_metadata:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
pull: true
|
pull: true
|
||||||
commands:
|
commands:
|
||||||
- mkdir public
|
- mkdir public
|
||||||
- gradle --build-cache :exportMetadata -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
- gradle --build-cache :exportMetadata -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
||||||
- mv version.json public/
|
- mv version.json public/
|
||||||
build_platform_jars:
|
build_platform_jars:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
commands:
|
commands:
|
||||||
- gradle --build-cache :launcher-dist:build -Pflavor=fat -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
- gradle --build-cache :launcher-dist:build -Pflavor=fat -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
||||||
- gradle --build-cache :launcher-dist:build -Pflavor=windows -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
- gradle --build-cache :launcher-dist:build -Pflavor=windows -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
||||||
|
@ -19,20 +19,20 @@ pipeline:
|
||||||
- for f in launcher-dist/build/libs/Inceptum-*-*-*.jar; do mv "$f" "public/Inceptum-$${f##*-}"; done
|
- for f in launcher-dist/build/libs/Inceptum-*-*-*.jar; do mv "$f" "public/Inceptum-$${f##*-}"; done
|
||||||
- mv public/Inceptum-fat.jar public/Inceptum.jar
|
- mv public/Inceptum-fat.jar public/Inceptum.jar
|
||||||
build_wrapper:
|
build_wrapper:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
commands:
|
commands:
|
||||||
- gradle --build-cache :wrapper:build -Pflavor=windows -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
- gradle --build-cache :wrapper:build -Pflavor=windows -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
||||||
- cp wrapper/build/libs/*.exe public/wrapper.exe
|
- cp wrapper/build/libs/*.exe public/wrapper.exe
|
||||||
- cp wrapper/build/libs/*-all.jar public/wrapper.jar
|
- cp wrapper/build/libs/*-all.jar public/wrapper.jar
|
||||||
publish_debug:
|
publish_debug:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
commands:
|
commands:
|
||||||
- gradle --build-cache build publish -Pflavor=maven -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
- gradle --build-cache build publish -Pflavor=maven -Ppublic -Ptimestamp=${CI_PIPELINE_STARTED}
|
||||||
secrets: [ maven_token, maven_name ]
|
secrets: [ maven_token, maven_name ]
|
||||||
when:
|
when:
|
||||||
- branch: master
|
- branch: master
|
||||||
publish_release:
|
publish_release:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
commands:
|
commands:
|
||||||
- gradle --build-cache build publish -Pflavor=maven -Ppublic -Prelease
|
- gradle --build-cache build publish -Pflavor=maven -Ppublic -Prelease
|
||||||
secrets: [ maven_token, maven_name ]
|
secrets: [ maven_token, maven_name ]
|
||||||
|
@ -40,7 +40,7 @@ pipeline:
|
||||||
- event: tag
|
- event: tag
|
||||||
branch: master
|
branch: master
|
||||||
portable:
|
portable:
|
||||||
image: gradle:jammy
|
image: gradle:jdk19-jammy
|
||||||
commands:
|
commands:
|
||||||
- apt update
|
- apt update
|
||||||
- apt install -y p7zip-full curl jq
|
- apt install -y p7zip-full curl jq
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package extensions.org.gtk.gtk.Widget;
|
||||||
|
|
||||||
|
import manifold.ext.rt.api.Extension;
|
||||||
|
import manifold.ext.rt.api.This;
|
||||||
|
import org.gtk.gtk.Widget;
|
||||||
|
|
||||||
|
@Extension
|
||||||
|
public class WidgetExt {
|
||||||
|
public static void setMargin(@This Widget thiz, int margin) {
|
||||||
|
thiz.marginVertical = margin;
|
||||||
|
thiz.marginHorizontal = margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMarginVertical(@This Widget thiz, int margin) {
|
||||||
|
thiz.marginTop = margin;
|
||||||
|
thiz.marginBottom = margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setMarginHorizontal(@This Widget thiz, int margin) {
|
||||||
|
thiz.marginStart = margin;
|
||||||
|
thiz.marginEnd = margin;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
package io.gitlab.jfronny.inceptum.gtk;
|
package io.gitlab.jfronny.inceptum.gtk;
|
||||||
|
|
||||||
|
import io.gitlab.jfronny.inceptum.launcher.system.launch.*;
|
||||||
import org.gtk.gtk.Application;
|
import org.gtk.gtk.Application;
|
||||||
import io.gitlab.jfronny.commons.ref.R;
|
import io.gitlab.jfronny.commons.ref.R;
|
||||||
import io.gitlab.jfronny.inceptum.common.Utils;
|
import io.gitlab.jfronny.inceptum.common.Utils;
|
||||||
|
@ -12,7 +13,6 @@ import io.gitlab.jfronny.inceptum.launcher.api.account.AccountManager;
|
||||||
import io.gitlab.jfronny.inceptum.launcher.api.account.MicrosoftAccount;
|
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.Instance;
|
||||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
|
import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList;
|
||||||
import io.gitlab.jfronny.inceptum.launcher.system.launch.InstanceLauncher;
|
|
||||||
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
|
import io.gitlab.jfronny.inceptum.launcher.system.setup.Steps;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -46,14 +46,14 @@ public class GtkMenubar {
|
||||||
launchMenu.clear();
|
launchMenu.clear();
|
||||||
try {
|
try {
|
||||||
InstanceList.forEach(entry -> {
|
InstanceList.forEach(entry -> {
|
||||||
launchMenu.literalButton(entry.id(), entry.toString(), () -> launch(entry));
|
launchMenu.literalButton(entry.id() + ".launch", entry.toString(), () -> launch(entry, LaunchType.Client));
|
||||||
});
|
});
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Utils.LOGGER.error("Could not generate launch menu", e);
|
Utils.LOGGER.error("Could not generate launch menu", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void launch(Instance instance) {
|
public static void launch(Instance instance, LaunchType launchType) {
|
||||||
//TODO show popup during launch w/ cancel option (lock main UI)
|
//TODO show popup during launch w/ cancel option (lock main UI)
|
||||||
Runnable launch = () -> {
|
Runnable launch = () -> {
|
||||||
try {
|
try {
|
||||||
|
@ -61,7 +61,14 @@ public class GtkMenubar {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e);
|
Utils.LOGGER.error("Could not redownload instance, trying to start anyways", e);
|
||||||
}
|
}
|
||||||
InstanceLauncher.launchClient(instance);
|
if (launchType == LaunchType.Client) InstanceLauncher.launchClient(instance);
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
InstanceLauncher.launch(instance, launchType, false, AccountManager.NULL_AUTH);
|
||||||
|
} catch (LaunchException | IOException e) {
|
||||||
|
LauncherEnv.showError("Could not start instance", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
if (instance.isSetupLocked) {
|
if (instance.isSetupLocked) {
|
||||||
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
|
LauncherEnv.showError(I18n.get("instance.launch.locked.setup"), I18n.get("instance.launch.locked"));
|
||||||
|
|
|
@ -1,80 +1,136 @@
|
||||||
package io.gitlab.jfronny.inceptum.gtk.control;
|
package io.gitlab.jfronny.inceptum.gtk.control;
|
||||||
|
|
||||||
import io.gitlab.jfronny.inceptum.gtk.util.ListIndexItem;
|
import io.github.jwharm.javagi.Signal;
|
||||||
import org.gnome.adw.ActionRow;
|
import io.gitlab.jfronny.commons.io.JFiles;
|
||||||
import org.gtk.gtk.*;
|
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.common.Utils;
|
||||||
import io.gitlab.jfronny.inceptum.gtk.GtkMenubar;
|
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.I18n;
|
||||||
import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance;
|
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.util.List;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
public class InstanceListEntryFactory extends SignalListItemFactory {
|
public class InstanceListEntryFactory extends SignalListItemFactory {
|
||||||
public InstanceListEntryFactory(List<Instance> instanceList) {
|
public InstanceListEntryFactory(List<Instance> instanceList, ActionMap actionMap) {
|
||||||
super();
|
super();
|
||||||
onSetup(item -> {
|
onSetup(item -> {
|
||||||
var thumbnail = new InstanceThumbnail();
|
var thumbnail = new InstanceThumbnail();
|
||||||
thumbnail.name = "inceptum-thumbnail";
|
thumbnail.name = "inceptum-thumbnail";
|
||||||
|
|
||||||
var launch = new Button();
|
var launch = new Button();
|
||||||
|
launch.addCssClass("flat");
|
||||||
launch.name = "inceptum-launch";
|
launch.name = "inceptum-launch";
|
||||||
launch.iconName = "computer-symbolic";
|
launch.iconName = "media-playback-start-symbolic";
|
||||||
launch.tooltipText = I18n.get("instance.launch");
|
launch.tooltipText = I18n.get("instance.launch");
|
||||||
launch.hasTooltip = true;
|
launch.hasTooltip = true;
|
||||||
|
|
||||||
var openDir = new Button();
|
var menu = new MenuButton();
|
||||||
openDir.name = "inceptum-open-dir";
|
menu.addCssClass("flat");
|
||||||
openDir.iconName = "folder-symbolic";
|
menu.iconName = "view-more-symbolic";
|
||||||
openDir.tooltipText = I18n.get("instance.directory");
|
menu.menuModel = new Menu();
|
||||||
openDir.hasTooltip = true;
|
|
||||||
|
|
||||||
var row = new ActionRow();
|
var row = new ActionRow();
|
||||||
|
row.margin = 8;
|
||||||
row.name = "inceptum-row";
|
row.name = "inceptum-row";
|
||||||
row.activatableWidget = launch;
|
row.activatableWidget = launch;
|
||||||
row.addPrefix(thumbnail);
|
row.addPrefix(thumbnail);
|
||||||
row.addSuffix(launch);
|
row.addSuffix(launch);
|
||||||
row.addSuffix(openDir);
|
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);
|
((ListItem) item).setChild(row);
|
||||||
|
|
||||||
//TODO server launch with network-server-symbolic
|
|
||||||
//TODO kill current instance
|
|
||||||
});
|
});
|
||||||
onBind(item -> {
|
Map<String, Set<Signal<?>>> toDisconnect = new HashMap<>();
|
||||||
ListItem li = (ListItem) item;
|
|
||||||
|
|
||||||
Instance instance = instanceList.get(((ListIndexItem) li.getItem()).getIntValue());
|
onBind(item -> {
|
||||||
ActionRow row = (ActionRow) li.child;
|
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 prefixes = (Box) row.firstChild.firstChild;
|
||||||
Box suffixes = (Box) row.firstChild.lastChild;
|
Box suffixes = (Box) row.firstChild.lastChild;
|
||||||
|
|
||||||
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom((Stack) prefixes.firstChild);
|
InstanceThumbnail thumbnail = InstanceThumbnail.castFrom((Stack) prefixes.firstChild);
|
||||||
Button launch = (Button) suffixes.firstChild;
|
Button launch = (Button) suffixes.firstChild;
|
||||||
Button openDir = (Button) launch.nextSibling;
|
MenuButton menuButton = (MenuButton) launch.nextSibling;
|
||||||
row.title = instance.toString();
|
return new Decomposed(instance, row, thumbnail, launch, (Menu) menuButton.menuModel);
|
||||||
|
}
|
||||||
// InstanceThumbnail thumbnail = new InstanceThumbnail(row.getFirstChild().cast());
|
|
||||||
// Label label = new Label(thumbnail.getNextSibling().cast());
|
|
||||||
// Button launch = new Button(label.getNextSibling().cast());
|
|
||||||
// Button openDir = new Button(launch.getNextSibling().cast());
|
|
||||||
|
|
||||||
thumbnail.bind(instance);
|
|
||||||
// label.setText(new Str(instance.toString()));
|
|
||||||
launch.onClicked(() -> GtkMenubar.launch(instance));
|
|
||||||
openDir.onClicked(() -> Utils.openFile(instance.path().toFile()));
|
|
||||||
|
|
||||||
//TODO why the hell does this crash the VM?
|
|
||||||
//TODO GestureClick.setButton(GDK_BUTTON_SECONDARY)
|
|
||||||
// var controller = new EventControllerLegacy();
|
|
||||||
// controller.onEvent(event -> {
|
|
||||||
// if (event.getEventType() == EventType.BUTTON_RELEASE) {
|
|
||||||
// Utils.LOGGER.info("Button " + new ButtonEvent(event.cast()).getButton());
|
|
||||||
// }
|
|
||||||
// return GTK.FALSE;
|
|
||||||
// });
|
|
||||||
// row.addController(controller);
|
|
||||||
//TODO edit button document-edit-symbolic -> edit-delete-symbolic, edit-copy-symbolic
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||||
|
|
||||||
|
import org.gtk.gio.MenuItem;
|
||||||
|
import org.gtk.gio.SimpleAction;
|
||||||
|
|
||||||
|
public class BuiltButtonItem extends BuiltMenuItem {
|
||||||
|
public BuiltButtonItem(SimpleAction action, MenuItem menuItem) {
|
||||||
|
super(action, menuItem);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||||
|
|
||||||
|
import org.gtk.gio.*;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class BuiltMenuItem {
|
||||||
|
protected final SimpleAction action;
|
||||||
|
protected final MenuItem menuItem;
|
||||||
|
|
||||||
|
protected BuiltMenuItem(@NotNull SimpleAction action, @Nullable MenuItem menuItem) {
|
||||||
|
this.action = Objects.requireNonNull(action);
|
||||||
|
this.menuItem = menuItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getEnabled() {
|
||||||
|
return action.getEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
action.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIconName(String iconName) {
|
||||||
|
Objects.requireNonNull(menuItem).icon = new ThemedIcon(iconName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,11 @@ import org.gtk.glib.Variant;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class RadioItem<T> extends MenuItem {
|
public class BuiltRadioItem<T> extends BuiltMenuItem {
|
||||||
private final List<T> options;
|
private final List<T> options;
|
||||||
|
|
||||||
public RadioItem(SimpleAction action, List<T> options) {
|
public BuiltRadioItem(SimpleAction action, List<T> options) {
|
||||||
super(action);
|
super(action, null);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
package io.gitlab.jfronny.inceptum.gtk.menu;
|
||||||
|
|
||||||
|
import org.gtk.gio.MenuItem;
|
||||||
import org.gtk.gio.SimpleAction;
|
import org.gtk.gio.SimpleAction;
|
||||||
import org.gtk.glib.Variant;
|
import org.gtk.glib.Variant;
|
||||||
|
|
||||||
public class ToggleItem extends MenuItem {
|
public class BuiltToggleItem extends BuiltMenuItem {
|
||||||
public ToggleItem(SimpleAction action) {
|
public BuiltToggleItem(SimpleAction action, MenuItem menuItem) {
|
||||||
super(action);
|
super(action, menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean getState() {
|
public boolean getState() {
|
|
@ -1,9 +0,0 @@
|
||||||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
|
||||||
|
|
||||||
import org.gtk.gio.SimpleAction;
|
|
||||||
|
|
||||||
public class ButtonItem extends MenuItem {
|
|
||||||
public ButtonItem(SimpleAction action) {
|
|
||||||
super(action);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,6 +9,7 @@ import org.gtk.glib.Variant;
|
||||||
import org.gtk.glib.VariantType;
|
import org.gtk.glib.VariantType;
|
||||||
import org.gtk.gtk.Application;
|
import org.gtk.gtk.Application;
|
||||||
import org.gtk.gtk.PopoverMenu;
|
import org.gtk.gtk.PopoverMenu;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -49,66 +50,84 @@ public class MenuBuilder {
|
||||||
this.prefix = Objects.requireNonNull(prefix);
|
this.prefix = Objects.requireNonNull(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ButtonItem button(String name, ThrowingRunnable<?> onClick) {
|
public BuiltButtonItem button(String name, ThrowingRunnable<?> onClick) {
|
||||||
return literalButton(name, I18n.get("menu." + prefix + name), onClick);
|
return literalButton(name, I18n.get("menu." + prefix + name), onClick);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ButtonItem literalButton(String internalName, String label, ThrowingRunnable<?> onClick) {
|
public BuiltButtonItem literalButton(String internalName, String label, ThrowingRunnable<?> onClick) {
|
||||||
internalName = prefix + internalName;
|
internalName = prefix + internalName;
|
||||||
SimpleAction sAct = new SimpleAction(internalName, null);
|
SimpleAction action = new SimpleAction(internalName, null);
|
||||||
addAction(internalName, sAct);
|
addAction(internalName, action);
|
||||||
sAct.onActivate(variant -> {
|
action.onActivate(variant -> {
|
||||||
try {
|
try {
|
||||||
onClick.run();
|
onClick.run();
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Utils.LOGGER.error("Could not execute action", e);
|
Utils.LOGGER.error("Could not execute action", e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
menu.appendItem(new MenuItem(label, "app." + internalName));
|
MenuItem menuItem = new MenuItem(label, "app." + internalName);
|
||||||
return new ButtonItem(sAct);
|
menu.appendItem(menuItem);
|
||||||
|
action.enabled = true;
|
||||||
|
return new BuiltButtonItem(action, menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ToggleItem toggle(String name, boolean initial, Consumer<Boolean> action) {
|
public BuiltToggleItem toggle(String name, boolean initial, Consumer<Boolean> onToggle) {
|
||||||
name = prefix + name;
|
name = prefix + name;
|
||||||
SimpleAction sAct = SimpleAction.newStateful(name, null, Variant.newBoolean(initial));
|
SimpleAction action = SimpleAction.newStateful(name, null, Variant.newBoolean(initial));
|
||||||
addAction(name, sAct);
|
addAction(name, action);
|
||||||
sAct.onActivate(variant -> {
|
action.onActivate(variant -> {
|
||||||
boolean state = !sAct.getState().getBoolean();
|
boolean state = !action.getState().getBoolean();
|
||||||
sAct.state = Variant.newBoolean(state);
|
action.state = Variant.newBoolean(state);
|
||||||
action.accept(state);
|
onToggle.accept(state);
|
||||||
});
|
});
|
||||||
menu.appendItem(new MenuItem(I18n.get("menu." + name), "app." + name));
|
MenuItem menuItem = new MenuItem(I18n.get("menu." + name), "app." + name);
|
||||||
return new ToggleItem(sAct);
|
menu.appendItem(menuItem);
|
||||||
|
return new BuiltToggleItem(action, menuItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> RadioItem<T> radio(String name, T initial, List<T> options, Consumer<T> action) {
|
public <T> BuiltRadioItem<T> radio(String name, T initial, List<T> options, Consumer<T> onCheck) {
|
||||||
return literalRadio(name, initial, options, (i, t) -> I18n.get("menu." + name, i), action);
|
return literalRadio(name, initial, options, (i, t) -> I18n.get("menu." + prefix + name, i), onCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> RadioItem<T> literalRadio(String name, T initial, List<T> options, BiFunction<Integer, T, String> stringifier, Consumer<T> action) {
|
public <T> BuiltRadioItem<T> literalRadio(String name, T initial, List<T> options, BiFunction<Integer, T, String> stringifier, Consumer<T> onCheck) {
|
||||||
Objects.requireNonNull(options);
|
Objects.requireNonNull(options);
|
||||||
name = prefix + name;
|
name = prefix + name;
|
||||||
SimpleAction sAct = SimpleAction.newStateful(name, new VariantType("i"), Variant.newInt32(options.indexOf(initial)));
|
SimpleAction action = SimpleAction.newStateful(name, new VariantType("i"), Variant.newInt32(options.indexOf(initial)));
|
||||||
addAction(name, sAct);
|
addAction(name, action);
|
||||||
sAct.onActivate(variant -> {
|
action.onActivate(variant -> {
|
||||||
sAct.state = variant;
|
action.state = variant;
|
||||||
action.accept(options.get(variant.getInt32()));
|
onCheck.accept(options.get(variant.getInt32()));
|
||||||
});
|
});
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (T option : options) {
|
for (T option : options) {
|
||||||
menu.appendItem(new MenuItem(stringifier.apply(i, option), "app." + name + "(" + i + ")"));
|
menu.appendItem(new MenuItem(stringifier.apply(i, option), "app." + name + "(" + i + ")"));
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return new RadioItem<>(sAct, options);
|
return new BuiltRadioItem<>(action, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MenuBuilder submenu(String name) {
|
public MenuBuilder submenu(String name) {
|
||||||
|
return literalSubmenu(name, I18n.get("menu." + prefix + name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuBuilder literalSubmenu(String name, String label) {
|
||||||
name = prefix + name;
|
name = prefix + name;
|
||||||
Menu submenu = new Menu();
|
Menu submenu = new Menu();
|
||||||
menu.appendSubmenu(I18n.get("menu." + name), submenu);
|
menu.appendSubmenu(label, submenu);
|
||||||
return new MenuBuilder(map, submenu, name);
|
return new MenuBuilder(map, submenu, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MenuBuilder section(String name) {
|
||||||
|
return literalSection(name, I18n.get("section." + prefix + name));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuBuilder literalSection(String name, @Nullable String label) {
|
||||||
|
name = prefix + name;
|
||||||
|
Menu section = new Menu();
|
||||||
|
menu.appendSection(label, section);
|
||||||
|
return new MenuBuilder(map, section, name);
|
||||||
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
menu.removeAll();
|
menu.removeAll();
|
||||||
refs.forEach((name, action) -> {
|
refs.forEach((name, action) -> {
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
package io.gitlab.jfronny.inceptum.gtk.menu;
|
|
||||||
|
|
||||||
import org.gtk.gio.SimpleAction;
|
|
||||||
|
|
||||||
public abstract class MenuItem {
|
|
||||||
protected final SimpleAction action;
|
|
||||||
|
|
||||||
public MenuItem(SimpleAction action) {
|
|
||||||
this.action = action;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getEnabled() {
|
|
||||||
return action.getEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
|
||||||
action.enabled = enabled;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -38,15 +38,15 @@ public class MainWindow extends ApplicationWindow {
|
||||||
|
|
||||||
HeaderBar header = new HeaderBar();
|
HeaderBar header = new HeaderBar();
|
||||||
Button newButton = new Button();
|
Button newButton = new Button();
|
||||||
newButton.setIconName("list-add-symbolic");
|
newButton.iconName = "list-add-symbolic";
|
||||||
newButton.onClicked(NewInstanceWindow::createAndShow);
|
newButton.onClicked(NewInstanceWindow::createAndShow);
|
||||||
|
|
||||||
MenuButton accountsButton = new MenuButton();
|
MenuButton accountsButton = new MenuButton();
|
||||||
accountsButton.setIconName("avatar-default-symbolic");
|
accountsButton.iconName = "avatar-default-symbolic";
|
||||||
accountsButton.setPopover(GtkMenubar.accountsMenu.asPopover());
|
accountsButton.menuModel = GtkMenubar.accountsMenu.menu;
|
||||||
|
|
||||||
listButton = new Button();
|
listButton = new Button();
|
||||||
listButton.setIconName("view-list-symbolic");
|
listButton.iconName = "view-list-symbolic";
|
||||||
listButton.onClicked(() -> {
|
listButton.onClicked(() -> {
|
||||||
InceptumConfig.listView = true;
|
InceptumConfig.listView = true;
|
||||||
InceptumConfig.saveConfig();
|
InceptumConfig.saveConfig();
|
||||||
|
@ -54,7 +54,7 @@ public class MainWindow extends ApplicationWindow {
|
||||||
});
|
});
|
||||||
|
|
||||||
gridButton = new Button();
|
gridButton = new Button();
|
||||||
gridButton.setIconName("view-grid-symbolic");
|
gridButton.iconName = "view-grid-symbolic";
|
||||||
gridButton.onClicked(() -> {
|
gridButton.onClicked(() -> {
|
||||||
InceptumConfig.listView = false;
|
InceptumConfig.listView = false;
|
||||||
InceptumConfig.saveConfig();
|
InceptumConfig.saveConfig();
|
||||||
|
@ -68,8 +68,8 @@ public class MainWindow extends ApplicationWindow {
|
||||||
uiMenu.button("preferences", () -> {}); //TODO preferences UI inspired by boxes
|
uiMenu.button("preferences", () -> {}); //TODO preferences UI inspired by boxes
|
||||||
uiMenu.button("about", AboutWindow::createAndShow);
|
uiMenu.button("about", AboutWindow::createAndShow);
|
||||||
MenuButton menuButton = new MenuButton();
|
MenuButton menuButton = new MenuButton();
|
||||||
menuButton.setIconName("open-menu-symbolic");
|
menuButton.iconName = "open-menu-symbolic";
|
||||||
menuButton.setPopover(uiMenu.asPopover());
|
menuButton.menuModel = uiMenu.menu;
|
||||||
|
|
||||||
header.packStart(newButton);
|
header.packStart(newButton);
|
||||||
|
|
||||||
|
@ -84,7 +84,11 @@ public class MainWindow extends ApplicationWindow {
|
||||||
|
|
||||||
listView = new Clamp();
|
listView = new Clamp();
|
||||||
listView.maximumSize = 900;
|
listView.maximumSize = 900;
|
||||||
listView.child = new ListView(singleSelection, new InstanceListEntryFactory(instanceList));
|
listView.child = new ListView(singleSelection, new InstanceListEntryFactory(instanceList, this));
|
||||||
|
listView.child.marginHorizontal = 24;
|
||||||
|
listView.child.marginVertical = 12;
|
||||||
|
listView.child.addCssClass("content");
|
||||||
|
listView.child.valign = Align.START;
|
||||||
gridView = new GridView(singleSelection, new InstanceGridEntryFactory(instanceList));
|
gridView = new GridView(singleSelection, new InstanceGridEntryFactory(instanceList));
|
||||||
empty = new StatusPage();
|
empty = new StatusPage();
|
||||||
empty.title = I18n.get("main.empty.title");
|
empty.title = I18n.get("main.empty.title");
|
||||||
|
|
|
@ -31,3 +31,10 @@ 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
|
main.empty.description=To get started, create (or import) a new instance using the + button
|
||||||
instance.directory=Open Directory
|
instance.directory=Open Directory
|
||||||
|
instance.launch.client=Launch Client
|
||||||
|
instance.launch.server=Launch Server
|
||||||
|
instance.settings=Settings
|
||||||
|
instance.copy=Duplicate
|
||||||
|
instance.delete=Delete
|
||||||
|
instance.copy.prompt=New Name
|
||||||
|
instance.copy.details=Please enter a name for the new instance
|
||||||
|
|
|
@ -31,3 +31,10 @@ 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 +
|
main.empty.description=Importiere oder erstelle um anzufangen eine Instanz mit dem +
|
||||||
instance.directory=Verzeichnis öffnen
|
instance.directory=Verzeichnis öffnen
|
||||||
|
instance.launch.client=Starte Client
|
||||||
|
instance.launch.server=Starte Server
|
||||||
|
instance.settings=Einstellungen
|
||||||
|
instance.copy=Klonen
|
||||||
|
instance.delete=Löschen
|
||||||
|
instance.copy.prompt=Neuer Name
|
||||||
|
instance.copy.details=Gib den Namen für die neue Instanz ein
|
||||||
|
|
Loading…
Reference in New Issue