package io.gitlab.jfronny.inceptum.gtk.window; 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; import io.gitlab.jfronny.inceptum.gtk.control.InstanceListEntryFactory; import io.gitlab.jfronny.inceptum.gtk.menu.MenuBuilder; import io.gitlab.jfronny.inceptum.gtk.util.I18n; import io.gitlab.jfronny.inceptum.launcher.system.instance.Instance; import io.gitlab.jfronny.inceptum.launcher.system.instance.InstanceList; import java.io.IOException; import java.net.URI; import java.nio.file.*; import java.util.ArrayList; import java.util.List; import static java.nio.file.StandardWatchEventKinds.*; public class MainWindow extends ApplicationWindow { private final Button listButton; private final Button gridButton; private final Stack stack; private final StatusPage empty; private final Clamp listView; private final GridView gridView; private final List instanceList; private final ListIndex instanceListIndex; public MainWindow(Application app) { super(app); HeaderBar header = new HeaderBar(); Button newButton = new Button(); newButton.setIconName("list-add-symbolic"); newButton.onClicked($ -> NewInstanceWindow.createAndShow()); MenuButton accountsButton = new MenuButton(); accountsButton.setIconName("avatar-default-symbolic"); accountsButton.setPopover(GtkMenubar.accountsMenu.asPopover()); listButton = new Button(); listButton.setIconName("view-list-symbolic"); listButton.onClicked($ -> { InceptumConfig.listView = true; InceptumConfig.saveConfig(); generateWindowBody(); }); gridButton = new Button(); gridButton.setIconName("view-grid-symbolic"); gridButton.onClicked($ -> { InceptumConfig.listView = false; InceptumConfig.saveConfig(); generateWindowBody(); }); //TODO search button like boxes MenuBuilder uiMenu = new MenuBuilder(app, new Menu(), "hamburger"); uiMenu.button("support", () -> Utils.openWebBrowser(new URI("https://gitlab.com/jfmods/inceptum/-/issues"))); uiMenu.button("preferences", () -> {}); //TODO preferences UI inspired by boxes uiMenu.button("about", AboutWindow::createAndShow); MenuButton menuButton = new MenuButton(); menuButton.setIconName("open-menu-symbolic"); menuButton.setPopover(uiMenu.asPopover()); header.packStart(newButton); header.packEnd(menuButton); header.packEnd(gridButton); header.packEnd(listButton); header.packEnd(accountsButton); instanceList = new ArrayList<>(); instanceListIndex = new ListIndex(); listView = new Clamp(); listView.maximumSize = 900; listView.child = new ListView(instanceListIndex.inSelectionModel(), new InstanceListEntryFactory(instanceList)); gridView = new GridView(instanceListIndex.inSelectionModel(), new InstanceGridEntryFactory(instanceList)); empty = new StatusPage(); 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.child = stack; setDefaultSize(360, 720); title = "Inceptum"; titlebar = header; showMenubar = false; child = scroll; generateWindowBody(); //TODO DropTarget to add mods/instances try { setupDirWatcher(); } catch (IOException e) { Utils.LOGGER.error("Could not set up watch service, live updates of the instance dir will be unavailable", e); } } 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(data -> { //TODO watch instance dirs for locks WatchKey key = ws.poll(); boolean instancesChanged = false; if (key != null) { for (WatchEvent event : key.pollEvents()) { if (event.context() instanceof Path p) { p = MetaHolder.INSTANCE_DIR.resolve(p); instancesChanged |= Files.exists(p.resolve("instance.json")); } } } if (instancesChanged) generateWindowBody(); return true; }, null); onCloseRequest($ -> { try { ws.close(); } catch (IOException ignored) { } GLib.sourceRemove(source); return false; }); } private void generateWindowBody() { 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.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); } } }