package io.gitlab.jfronny.inceptum.gtk.window; import ch.bailu.gtk.GTK; import ch.bailu.gtk.adw.Clamp; import ch.bailu.gtk.adw.StatusPage; import ch.bailu.gtk.bridge.ListIndex; import ch.bailu.gtk.gio.Menu; import ch.bailu.gtk.glib.Glib; import ch.bailu.gtk.gtk.*; import ch.bailu.gtk.type.Str; 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.util.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(new Str("list-add-symbolic")); newButton.onClicked(NewInstanceWindow::createAndShow); MenuButton accountsButton = new MenuButton(); accountsButton.setIconName(new Str("avatar-default-symbolic")); accountsButton.setPopover(GtkMenubar.accountsMenu.asPopover()); listButton = new Button(); listButton.setIconName(new Str("view-list-symbolic")); listButton.onClicked(() -> { InceptumConfig.listView = true; InceptumConfig.saveConfig(); generateWindowBody(); }); gridButton = new Button(); gridButton.setIconName(new Str("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(new Str("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.setMaximumSize(900); listView.setChild(new ListView(instanceListIndex.inSelectionModel(), new InstanceListEntryFactory(instanceList))); gridView = new GridView(instanceListIndex.inSelectionModel(), new InstanceGridEntryFactory(instanceList)); empty = new StatusPage(); empty.setTitle(I18n.str("main.empty.title")); empty.setDescription(I18n.str("main.empty.description")); //TODO empty.setIconName(new Str()); stack = new Stack(); stack.addChild(listView); stack.addChild(gridView); ScrolledWindow scroll = new ScrolledWindow(); scroll.setPolicy(PolicyType.NEVER, PolicyType.AUTOMATIC); scroll.setChild(stack); setDefaultSize(360, 720); setTitle(new Str("Inceptum")); setTitlebar(header); setShowMenubar(GTK.FALSE); setChild(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(user_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 GTK.TRUE; }, null); onCloseRequest(() -> { try { ws.close(); } catch (IOException ignored) { } Glib.sourceRemove(source); return GTK.FALSE; }); } private void generateWindowBody() { if (listButton != null) listButton.setVisible(GTK.is(!InceptumConfig.listView)); if (gridButton != null) gridButton.setVisible(GTK.is(InceptumConfig.listView)); try { instanceList.clear(); InstanceList.forEach(instanceList::add); instanceListIndex.setSize(instanceList.size()); if (InstanceList.isEmpty()) stack.setVisibleChild(empty); else if (InceptumConfig.listView) stack.setVisibleChild(listView); else stack.setVisibleChild(gridView); } catch (IOException e) { Utils.LOGGER.error("Could not generate window body", e); } } }