diff --git a/libs/libRefTools.jar b/libs/libRefTools.jar index 4f2a003..a53cd8a 100644 Binary files a/libs/libRefTools.jar and b/libs/libRefTools.jar differ diff --git a/src/Launcher/Main.java b/src/Launcher/Main.java index c27941e..dca1bf1 100644 --- a/src/Launcher/Main.java +++ b/src/Launcher/Main.java @@ -13,16 +13,19 @@ package Launcher; import com.tofvesson.reflection.SafeReflection; import javafx.application.Application; import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.Parent; import javafx.scene.Scene; -import javafx.scene.control.Button; -import javafx.scene.control.TextField; +import javafx.scene.control.*; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.Pane; import javafx.scene.shape.Rectangle; import javafx.stage.Stage; import javafx.stage.StageStyle; + import java.net.URL; + import com.tofvesson.async.*; public class Main extends Application { @@ -30,13 +33,13 @@ public class Main extends Application { public static final URL mainLauncher = Main.class.getResource("../assets/layout/main.fxml"); // Launcher body private double xOffset = 0, yOffset = 0; // Offsets for dragging - private Button exit, min, Home_btn, Modpack_btn, Settings_btn, Instance_btn, Settings_General_btn, Settings_Minecraft_btn; // Define buttons + private Button exit, min, Home_btn, Modpack_btn, Settings_btn, Instance_btn; // Define buttons private ImageView icon; private TextField Search_modpacks; private Image appIcon; private Rectangle dragBar; // Draggable top bar private Pane root, tab; - private Tabs activeTab = Tabs.Home; + private Node activeTab, settings_activeTab; Async stringUpdater; @Override @@ -61,8 +64,6 @@ public class Main extends Application { Modpack_btn = (Button) root.lookup("#Modpacks-btn"); Settings_btn = (Button) root.lookup("#Settings-btn"); Instance_btn = (Button) root.lookup("#Instance-btn"); - Settings_General_btn = (Button) root.lookup("Settings-Gen-btn"); - Settings_Minecraft_btn = (Button) root.lookup("Settings-Mine-btn"); tab = (Pane) root.lookup("#tab"); @@ -75,32 +76,57 @@ public class Main extends Application { min.setOnMouseClicked(event -> primaryStage.setIconified(true)); // Minimizes the program if minimize button is clicked Home_btn.setOnMouseClicked(event ->{ - if(activeTab!=Tabs.Home){ - (activeTab=Tabs.Home).switchTab(tab); + if(!activeTab.equals(Home_btn)){ + updateTabSelection(Home_btn); + Tabs.switchTab("home", tab); } }); // Sets the active tab to the home tab unless it's already active Modpack_btn.setOnMouseClicked(event ->{ - if(activeTab!=Tabs.Modpacks){ + if(!activeTab.equals(Modpack_btn)){ + updateTabSelection(Modpack_btn); + Tabs.switchTab("modpacks", tab); if(stringUpdater!=null && stringUpdater.isAlive()) stringUpdater.cancel(); - (activeTab=Tabs.Modpacks).switchTab(tab); // Sets the active tab to the modpacks tab unless it's already active - - stringUpdater = new Async(SafeReflection.getFirstMethod(Main.class, "detectStringUpdate"), Tabs.Modpacks.loaded.lookup("#search-modpacks")); + stringUpdater = new Async(SafeReflection.getFirstMethod(Main.class, "detectStringUpdate"), Tabs.load("settings").lookup("#search-modpacks")); } }); Instance_btn.setOnMouseClicked(event -> { - if(activeTab!=Tabs.Instance){ - (activeTab = Tabs.Instance).switchTab(tab); + if(!activeTab.equals(Instance_btn)){ + updateTabSelection(Instance_btn); + Tabs.switchTab("instance", tab); + DialogPane d = new DialogPane(); + Tabs.load("instance").lookup("#Launch-VM").setOnMouseClicked(event1 -> { + Dialog d1 = new Dialog<>(); + DialogPane d2 = d1.getDialogPane(); + d2.setContent(new TextArea("Hello")); + d1.show(); + }); } }); Settings_btn.setOnMouseClicked(event ->{ - if(activeTab!=Tabs.Settings){ - (activeTab=Tabs.Settings).switchTab(tab); // Sets the active tab to the settings tab unless it's already active + if(!activeTab.equals(Settings_btn)){ + updateTabSelection(Settings_btn); + Node n = Tabs.switchTab("settings", tab); // Sets the active tab to the settings tab unless it's already active + (settings_activeTab=n.lookup("#Settings-Gen-btn")).setOnMouseClicked(event1 -> { + // Generic Settings Sub-tab + if(!settings_activeTab.equals(n.lookup("#Settings-Gen-btn"))){ + updateSettingsTabSelection(n.lookup("#Settings-Gen-btn")); + Node genericLayout = Tabs.switchTab("settings_generic", (Pane) n.lookup("#Settings-Pane")); + } + }); + + n.lookup("#Settings-Mine-btn").setOnMouseClicked(event1 -> { + // Minecraft Settings Sub-tab + if(!settings_activeTab.equals(n.lookup("#Settings-Mine-btn"))){ + updateSettingsTabSelection(n.lookup("#Settings-Mine-btn")); + Node minecraftLayout = Tabs.switchTab("settings_minecraft", (Pane) n.lookup("#Settings-Pane")); + } + }); } }); @@ -115,7 +141,8 @@ public class Main extends Application { }); // Set up default layout - Tabs.Home.switchTab(tab); + activeTab = Home_btn; // Update selected tab + Tabs.switchTab("home", tab); icon.setImage(appIcon); } @@ -123,9 +150,29 @@ public class Main extends Application { launch(args); } + /** + * Search for packs with an 80% match compared to detected string. + * @param toRead TextField to read from. + */ public static void detectStringUpdate(TextField toRead){ String s = ""; while(true) if(!s.equals(toRead.getText())) System.out.println(s = toRead.getText()); } + + void updateTabSelection(Node newTab){ + activeTab.getStyleClass().remove("selected"); + activeTab.getStyleClass().add("tab"); + activeTab = newTab; + activeTab.getStyleClass().remove("tab"); + activeTab.getStyleClass().add("selected"); + } + + void updateSettingsTabSelection(Node newTab){ + settings_activeTab.getStyleClass().remove("selected"); + settings_activeTab.getStyleClass().add("tab"); + settings_activeTab = newTab; + settings_activeTab.getStyleClass().remove("tab"); + settings_activeTab.getStyleClass().add("selected"); + } } diff --git a/src/Launcher/Tabs.java b/src/Launcher/Tabs.java index d82baba..e8b844b 100644 --- a/src/Launcher/Tabs.java +++ b/src/Launcher/Tabs.java @@ -1,37 +1,73 @@ package Launcher; +import com.tofvesson.collections.ShiftingList; import javafx.fxml.FXMLLoader; -import javafx.scene.Parent; +import javafx.scene.Node; import javafx.scene.layout.Pane; +import javafx.util.Pair; import java.io.IOException; import java.net.URL; -public enum Tabs { +@SuppressWarnings("unused") +public class Tabs { - Modpacks(Tabs.class.getResource("../assets/layout/modpacks.fxml")), - Home(Tabs.class.getResource("../assets/layout/home.fxml")), - Settings(Tabs.class.getResource("../assets/layout/settings.fxml")), - Instance(Tabs.class.getResource("../assets/layout/instance.fxml")); + private static final ShiftingList> loaded = new ShiftingList<>(35); // Memory-efficient list of loaded files /** - * Url referencing xml. + * Loads layout from file in layout assets folder. If layout is already loaded, + * Tabs won't bother with reloading and will instead return the cached version. + * @param fileName Name of fxml file to load. (Must be located in /assets/layout/ folder or name must define name subfolder in layouts folder) + * @return Generified object referring to loaded resource. */ - public final URL url; - - /** - * Loaded layout - */ - public final Parent loaded; - - Tabs(URL url){ - this.url = url; - Parent p = null; - try { p = FXMLLoader.load(url); } catch (IOException e) { e.printStackTrace(); } - loaded = p; + public static Node load(String fileName){ + if(!fileName.endsWith(".fxml")) fileName+=".fxml"; + URL file = Main.class.getResource("../assets/layout/"+fileName); + try { + final boolean[] b = {false}; + loaded.stream().filter(p -> p.getKey().equals(file)).forEach(p->b[0]=true); + if(!b[0]) loaded.add(new Pair<>(file, FXMLLoader.load(file))); // Load file if it isn't already loaded + final Node[] p1 = new Node[]{new Pane()}; + loaded.stream().filter(p->p.getKey().equals(file)).forEach(p->p1[0]=p.getValue()); + return p1[0]; + } catch (IOException e) { + e.printStackTrace(); + return new Pane(); // Returns empty layout if all else fails + } } - public void switchTab(Pane holder){ - holder.getChildren().clear(); - holder.getChildren().add(loaded); + /** + * Switches the currently loaded tab in holder pane. Removes current children from holder and adds new tab instead. + * If holder already contains layout, method simply returns the loaded resource. + * @param newTabName Name of file containing the new tab data. + * @param holder Pane where tab should be loaded to. + * @return Generified object referring to loaded resource. + */ + public static Node switchTab(String newTabName, Pane holder){ + Node n = load(newTabName); + if(!holder.getChildren().contains(n)) { + holder.getChildren().clear(); + holder.getChildren().add(n); + } + return n; + } + + /** + * Forces unloading of resource to free up resources and/or clear data. + * @param fileName Name of resource to unload. + */ + public static void unloadTab(String fileName){ + if(!fileName.endsWith(".fxml")) fileName+=".fxml"; + URL file = Main.class.getResource("../assets/layout/"+fileName); + loaded.stream().filter(p->p.getKey().equals(file)).forEach(loaded::remove); + } + + /** + * Forces unloading and the subsequent loading of a layout resource. + * @param fileName Name of resource to reload. + * @return Newly loaded layout. + */ + public static Node reloadTab(String fileName){ + unloadTab(fileName); + return load(fileName); } } diff --git a/src/assets/layout/instance_userinfo.fxml b/src/assets/layout/instance_userinfo.fxml new file mode 100644 index 0000000..9db0fb8 --- /dev/null +++ b/src/assets/layout/instance_userinfo.fxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/layout/main.fxml b/src/assets/layout/main.fxml index 8d0a86b..7e4e3e6 100644 --- a/src/assets/layout/main.fxml +++ b/src/assets/layout/main.fxml @@ -7,7 +7,7 @@ - + - - - + + diff --git a/src/assets/layout/settings_generic.fxml b/src/assets/layout/settings_generic.fxml new file mode 100644 index 0000000..9db0fb8 --- /dev/null +++ b/src/assets/layout/settings_generic.fxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/layout/settings_minecraft.fxml b/src/assets/layout/settings_minecraft.fxml new file mode 100644 index 0000000..9db0fb8 --- /dev/null +++ b/src/assets/layout/settings_minecraft.fxml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/assets/style/nav.css b/src/assets/style/nav.css index 4f1feff..435225c 100644 --- a/src/assets/style/nav.css +++ b/src/assets/style/nav.css @@ -13,15 +13,27 @@ #min:hover, #exit:hover{ -fx-background-color: #bf0000; } -#Home-btn, #Modpacks-btn, #Settings-btn, #Instance-btn, #Settings-Gen-btn, #Settings-Mine-btn{ - -fx-background-color: rgba(0, 0, 0, 0); -} -#Home-btn:hover, #Modpacks-btn:hover, #Settings-btn:hover, #Instance-btn:hover, #Settings-Gen-btn:hover, #Settings-Mine-btn:hover { - -fx-background-color: #0c182d; - -fx-background-radius: 0em; -} #search-modpacks { -fx-text-inner-color: white; -fx-background-color: rgba(0, 0, 0, 0.5); -fx-padding: 10px; +} + +.tab { + -fx-background-color: rgba(0, 0, 0, 0); + -fx-background-radius: 0em; +} + +.tab:hover{ + -fx-background-color: #0c182d; + +} + +.selected { + -fx-background-color: #0c182d; + -fx-background-radius: 0em; +} + +.selected:hover { + -fx-background-color: #050b14; } \ No newline at end of file