Revise IDE configurations (KDEV4)
38
src/main/java/org/worlio/WorldsOrganizer/AppIcon.java
Normal file
@@ -0,0 +1,38 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import javafx.scene.image.Image;
|
||||
|
||||
public class AppIcon {
|
||||
|
||||
public static Image logo = new Image(Main.class.getResourceAsStream("/logo.png"));
|
||||
|
||||
public static Image config = new Image(Main.class.getResourceAsStream("/icons/conf.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image newFile = new Image(Main.class.getResourceAsStream("/icons/file-plus.png"), getSize(), getSize(), false, true);
|
||||
public static Image openFile = new Image(Main.class.getResourceAsStream("/icons/folder.png"), getSize(), getSize(), false, true);
|
||||
public static Image saveFile = new Image(Main.class.getResourceAsStream("/icons/save.png"), getSize(), getSize(), false, true);
|
||||
public static Image saveFileAs = new Image(Main.class.getResourceAsStream("/icons/save-as.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image undo = new Image(Main.class.getResourceAsStream("/icons/undo.png"), getSize(), getSize(), false, true);
|
||||
public static Image redo = new Image(Main.class.getResourceAsStream("/icons/redo.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image quitApp = new Image(Main.class.getResourceAsStream("/icons/quit.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image add = new Image(Main.class.getResourceAsStream("/icons/plus.png"), getSize(), getSize(), false, true);
|
||||
public static Image remove = new Image(Main.class.getResourceAsStream("/icons/delete.png"), getSize(), getSize(), false, true);
|
||||
public static Image removeAll = new Image(Main.class.getResourceAsStream("/icons/delete-all.png"), getSize(), getSize(), false, true);
|
||||
public static Image moveUp = new Image(Main.class.getResourceAsStream("/icons/up.png"), getSize(), getSize(), false, true);
|
||||
public static Image moveDown = new Image(Main.class.getResourceAsStream("/icons/down.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image findReplace = new Image(Main.class.getResourceAsStream("/icons/find.png"), getSize(), getSize(), false, true);
|
||||
public static Image linkCheck = new Image(Main.class.getResourceAsStream("/icons/link.png"), getSize(), getSize(), false, true);
|
||||
|
||||
public static Image unknownFile = new Image(Main.class.getResourceAsStream("/icons/file.png"), getSize(), getSize(), false, true);
|
||||
public static Image avatarFile = new Image(Main.class.getResourceAsStream("/icons/avatar.png"), getSize(), getSize(), false, true);
|
||||
public static Image markFile = new Image(Main.class.getResourceAsStream("/icons/mark.png"), getSize(), getSize(), false, true);
|
||||
|
||||
private static int getSize() {
|
||||
return Main.configManager.getIntValue(ConfigEntry.iconSize);
|
||||
}
|
||||
|
||||
}
|
||||
28
src/main/java/org/worlio/WorldsOrganizer/AvatarObject.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public class AvatarObject implements WorldList {
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
AvatarObject(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String code) {
|
||||
this.value = code;
|
||||
}
|
||||
}
|
||||
9
src/main/java/org/worlio/WorldsOrganizer/Command.java
Normal file
@@ -0,0 +1,9 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
interface Command {
|
||||
|
||||
public void execute();
|
||||
|
||||
public void undo();
|
||||
|
||||
}
|
||||
57
src/main/java/org/worlio/WorldsOrganizer/CommandStack.java
Normal file
@@ -0,0 +1,57 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class CommandStack {
|
||||
private List<Command> commands = Collections.emptyList();
|
||||
private int nextPointer = 0;
|
||||
|
||||
public void doCommand(Command command) {
|
||||
List<Command> newList = new ArrayList<>(nextPointer + 1);
|
||||
|
||||
for(int k = 0; k < nextPointer; k++) {
|
||||
newList.add(commands.get(k));
|
||||
}
|
||||
|
||||
newList.add(command);
|
||||
|
||||
commands = newList;
|
||||
nextPointer++;
|
||||
|
||||
// Do the command here, or return it to whatever called this to be done, or maybe it has already been done by now or something
|
||||
// (I can only guess on what your code currently looks like...)
|
||||
command.execute();
|
||||
}
|
||||
|
||||
public boolean canUndo() {
|
||||
return nextPointer > 0;
|
||||
}
|
||||
|
||||
public void undo() {
|
||||
if(canUndo()) {
|
||||
nextPointer--;
|
||||
Command commandToUndo = commands.get(nextPointer);
|
||||
// Undo the command, or return it to whatever called this to be undone, or something
|
||||
commandToUndo.undo();
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot undo");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canRedo() {
|
||||
return nextPointer < commands.size();
|
||||
}
|
||||
|
||||
public void redo() {
|
||||
if(canRedo()) {
|
||||
Command commandToDo = commands.get(nextPointer);
|
||||
nextPointer++;
|
||||
// Do the command, or return it to whatever called this to be re-done, or something
|
||||
commandToDo.execute();
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot redo");
|
||||
}
|
||||
}
|
||||
}
|
||||
197
src/main/java/org/worlio/WorldsOrganizer/ConfigManager.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
enum ToolBarPosition {
|
||||
|
||||
TOP("Top", 0),
|
||||
RIGHT("Right", 1),
|
||||
BOTTOM("Bottom", 2),
|
||||
LEFT("Left", 3);
|
||||
|
||||
private String name;
|
||||
private int value;
|
||||
|
||||
ToolBarPosition(String name, int value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
enum ConfigEntry {
|
||||
updateURL("update-url"),
|
||||
iconSize("icon-size"),
|
||||
fileBackup("file-backup"),
|
||||
darkMode("dark-mode"),
|
||||
toolbarPos("toolbar-position"),
|
||||
channel("channel"),
|
||||
status("show-status"),
|
||||
debug("debug");
|
||||
|
||||
private String name;
|
||||
|
||||
ConfigEntry(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private File configFile;
|
||||
|
||||
public static final List<String> channels = Arrays.asList("stable", "beta");
|
||||
public static final List<String> toolBarPos = Arrays.asList("Top", "Right", "Bottom", "Left");
|
||||
|
||||
private static HashMap<String, Object> defaultConfiguration = new HashMap<>();
|
||||
static HashMap<String, Object> configuration = new HashMap<>();
|
||||
private static ObjectMapper mapper;
|
||||
|
||||
private void initialize() {
|
||||
mapper = new ObjectMapper();
|
||||
Console.print("Initializing default config values", 1, ConsoleType.INFO);
|
||||
defaultConfiguration.put(ConfigEntry.updateURL.name(), "https://worlio.com/WorldsOrganizer.json");
|
||||
defaultConfiguration.put(ConfigEntry.iconSize.name(), 24);
|
||||
defaultConfiguration.put(ConfigEntry.fileBackup.name(), true);
|
||||
defaultConfiguration.put(ConfigEntry.darkMode.name(), false);
|
||||
defaultConfiguration.put(ConfigEntry.toolbarPos.name(), 3);
|
||||
defaultConfiguration.put(ConfigEntry.channel.name(), "stable");
|
||||
defaultConfiguration.put(ConfigEntry.status.name(), true);
|
||||
defaultConfiguration.put(ConfigEntry.debug.name(), false);
|
||||
}
|
||||
|
||||
public ConfigManager() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
public ConfigManager(File file) {
|
||||
initialize();
|
||||
configFile = file;
|
||||
try {
|
||||
if (!configFile.exists()) {
|
||||
Console.print("Config doesn't exist! Writing new one...", 1, ConsoleType.INFO);
|
||||
write();
|
||||
configuration = defaultConfiguration;
|
||||
} else {
|
||||
Console.print("Mapping config", 1, ConsoleType.INFO);
|
||||
configuration = mapper.readValue(new FileInputStream(configFile), new TypeReference<HashMap<String, Object>>() {});
|
||||
}
|
||||
} catch (IOException ioException) {
|
||||
write();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean write() {
|
||||
Console.print("Updating config", ConsoleType.INFO);
|
||||
return write(configFile);
|
||||
}
|
||||
|
||||
public boolean write(HashMap<String, Object> hash) {
|
||||
if (!configFile.exists()) {
|
||||
if (!createFile(configFile)) return false;
|
||||
}
|
||||
assert configFile.exists();
|
||||
try(FileOutputStream fos = new FileOutputStream(configFile);
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
|
||||
bos.write(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(hash).getBytes());
|
||||
bos.close();
|
||||
fos.close();
|
||||
configuration = mapper.readValue(new FileInputStream(configFile), new TypeReference<HashMap<String, Object>>() {
|
||||
});
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Console.print("IOException encountered while writing config file. Aborted!", ConsoleType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean write(File file) {
|
||||
if (!file.exists()) {
|
||||
if (!createFile(file)) return false;
|
||||
}
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
try(FileOutputStream fos = new FileOutputStream(configFile);
|
||||
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
|
||||
bos.write(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(configuration).getBytes());
|
||||
bos.close();
|
||||
fos.close();
|
||||
configuration = mapper.readValue(new FileInputStream(file), new TypeReference<HashMap<String, Object>>() {});
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
Console.print("IOException encountered while writing config file. Aborted!", ConsoleType.ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean createFile(File file) {
|
||||
try {
|
||||
assert file.createNewFile();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getBooleanValue(ConfigEntry entry) {
|
||||
return (boolean)getValue(entry);
|
||||
}
|
||||
|
||||
public String getStringValue(ConfigEntry entry) {
|
||||
return (String)getValue(entry);
|
||||
}
|
||||
|
||||
public int getIntValue(ConfigEntry entry) {
|
||||
return (int)getValue(entry);
|
||||
}
|
||||
|
||||
public double getDoubleValue(ConfigEntry entry) {
|
||||
return (double)getValue(entry);
|
||||
}
|
||||
|
||||
private Object getValue(ConfigEntry entry) {
|
||||
try {
|
||||
Object o = configuration.get(entry.name());
|
||||
if (o == null) throw new NullPointerException();
|
||||
else return o;
|
||||
} catch (NullPointerException e) {
|
||||
return defaultConfiguration.get(entry.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void set(ConfigEntry entry, Object value) {
|
||||
if (configuration.containsKey(entry.name())) configuration.replace(entry.name(), value);
|
||||
else configuration.put(entry.name(), value);
|
||||
}
|
||||
|
||||
public void setValue(ConfigEntry entry, Object value) {
|
||||
switch (entry) {
|
||||
default:
|
||||
set(entry, value);
|
||||
break;
|
||||
case toolbarPos:
|
||||
switch ((String)value) {
|
||||
case "Top":
|
||||
set(entry, 0);
|
||||
break;
|
||||
case "Right":
|
||||
set(entry, 1);
|
||||
break;
|
||||
case "Bottom":
|
||||
set(entry, 2);
|
||||
break;
|
||||
default:
|
||||
case "Left":
|
||||
set(entry, 3);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
139
src/main/java/org/worlio/WorldsOrganizer/Console.java
Normal file
@@ -0,0 +1,139 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
enum ConsoleType {
|
||||
ERROR(5),
|
||||
WARNING(4),
|
||||
DEBUG(3),
|
||||
SUCCESS(2),
|
||||
INFO(1),
|
||||
DEFAULT(0);
|
||||
|
||||
private final int value;
|
||||
|
||||
ConsoleType(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public class Console {
|
||||
|
||||
public static final String RESET = "\u001B[0m";
|
||||
public static final String RED = "\u001B[31m";
|
||||
public static final String GREEN = "\u001B[32m";
|
||||
public static final String YELLOW = "\u001B[33m";
|
||||
public static final String BLUE = "\u001B[34m";
|
||||
public static final String CYAN = "\u001B[36m";
|
||||
|
||||
final static Properties properties = new Properties();
|
||||
|
||||
public static void print(String message) {
|
||||
print(message, ConsoleType.INFO);
|
||||
}
|
||||
|
||||
public static void print(String message, ConsoleType type) {
|
||||
print(message, 0, type);
|
||||
}
|
||||
|
||||
public static void print(String message, int debug, ConsoleType type) {
|
||||
if (Main.debugMode >= debug) {
|
||||
String output = "";
|
||||
switch (type) {
|
||||
case DEFAULT:
|
||||
break;
|
||||
case INFO:
|
||||
output = BLUE + "INFO " + RESET;
|
||||
break;
|
||||
case SUCCESS:
|
||||
output = GREEN + "SUCCESS " + RESET;
|
||||
break;
|
||||
case DEBUG:
|
||||
output = CYAN + "DEBUG " + RESET;
|
||||
break;
|
||||
case WARNING:
|
||||
output = YELLOW + "WARNING " + RESET;
|
||||
break;
|
||||
case ERROR:
|
||||
output = RED + "ERROR " + RESET;
|
||||
break;
|
||||
}
|
||||
output += message;
|
||||
System.out.println(output);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getProperty(String property) {
|
||||
try {
|
||||
properties.load(Main.class.getClassLoader().getResourceAsStream("project.properties"));
|
||||
return properties.getProperty(property);
|
||||
} catch (IOException e) {
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
public static String getVersion(){
|
||||
return getProperty("version");
|
||||
}
|
||||
|
||||
public static String getDate(){
|
||||
return getProperty("buildDate");
|
||||
}
|
||||
|
||||
public static String getHelp() {
|
||||
String command;
|
||||
command = "WorldsOrganizer.jar [OPTIONS]\n" +
|
||||
"Commands:\n" +
|
||||
commandCreate(" --debug=n", "Enable debug mode, which displays extra log information in the command-line. (1 - Logging, 2 - Complete Debug)") + "\n" +
|
||||
commandCreate("-i --input", "Start application with input files.") + "\n" +
|
||||
commandCreate("-h --help", "Show this output.");
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
private static String commandCreate(String cmd, String info) {
|
||||
return " " + cmd + " ".substring(cmd.length()) + info;
|
||||
}
|
||||
|
||||
public static boolean testURL(String address) throws IOException {
|
||||
int responseCode;
|
||||
try {
|
||||
URL url = new URL(address);
|
||||
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
|
||||
huc.setRequestMethod("HEAD");
|
||||
huc.setConnectTimeout(15000);
|
||||
|
||||
responseCode = huc.getResponseCode();
|
||||
} catch (Exception e) {
|
||||
responseCode = 404;
|
||||
}
|
||||
|
||||
return HttpURLConnection.HTTP_OK == responseCode;
|
||||
}
|
||||
|
||||
public static void process() {
|
||||
Dialog.process();
|
||||
}
|
||||
|
||||
public static File getParent() {
|
||||
try {
|
||||
return new File(Main.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getParentFile();
|
||||
} catch (URISyntaxException e) {
|
||||
Dialog.showException(e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String changelogify(List<String> list) {
|
||||
StringBuilder changes = new StringBuilder();
|
||||
for (String line : list) {
|
||||
changes.append(" - ").append(line).append("\n");
|
||||
}
|
||||
return changes.toString();
|
||||
}
|
||||
|
||||
}
|
||||
170
src/main/java/org/worlio/WorldsOrganizer/Dialog.java
Normal file
@@ -0,0 +1,170 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Dialog {
|
||||
|
||||
public static void showWindowDialog(String title, Pane pane) {
|
||||
showWindowDialog(title, pane, null);
|
||||
}
|
||||
|
||||
public static void showWindowDialog(String title, Pane pane, Collection<Button> buttons) {
|
||||
Stage dStage = new Stage();
|
||||
dStage.initOwner(Main.mainStage);
|
||||
dStage.setTitle(title);
|
||||
|
||||
Button cancelButton = new Button("Close");
|
||||
cancelButton.setCancelButton(true);
|
||||
cancelButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> dStage.close());
|
||||
|
||||
ButtonBar buttonBar = new ButtonBar();
|
||||
buttonBar.getButtons().add(cancelButton);
|
||||
if (buttons != null) buttonBar.getButtons().addAll(buttons);
|
||||
buttonBar.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
dStage.setMinWidth(400);
|
||||
dStage.setMinHeight(400);
|
||||
|
||||
dStage.setScene(new Scene(new VBox(pane, buttonBar), 400, 400));
|
||||
dStage.show();
|
||||
}
|
||||
|
||||
public static void showError(String header, String content) {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle("An Error Occurred");
|
||||
alert.setHeaderText(header);
|
||||
alert.setContentText(content);
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
public static void showException(Exception ex) {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle("Exception Dialog");
|
||||
alert.setHeaderText("An Exception was encountered.");
|
||||
alert.setContentText("Please file a bug report if this problem persists.");
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
StringWriter sw = new StringWriter();
|
||||
PrintWriter pw = new PrintWriter(sw);
|
||||
ex.printStackTrace(pw);
|
||||
String exceptionText = sw.toString();
|
||||
|
||||
Label label = new Label("The exception stacktrace was:");
|
||||
|
||||
TextArea textArea = new TextArea(exceptionText);
|
||||
textArea.setEditable(false);
|
||||
textArea.setWrapText(true);
|
||||
|
||||
textArea.setMaxWidth(Double.MAX_VALUE);
|
||||
textArea.setMaxHeight(Double.MAX_VALUE);
|
||||
GridPane.setVgrow(textArea, Priority.ALWAYS);
|
||||
GridPane.setHgrow(textArea, Priority.ALWAYS);
|
||||
|
||||
GridPane expContent = new GridPane();
|
||||
expContent.setMaxWidth(Double.MAX_VALUE);
|
||||
expContent.add(label, 0, 0);
|
||||
expContent.add(textArea, 0, 1);
|
||||
|
||||
alert.getDialogPane().setExpandableContent(expContent);
|
||||
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
public static WorldsType newFileList() {
|
||||
List<String> choices = new ArrayList<>();
|
||||
choices.add("Avatars");
|
||||
choices.add("WorldsMarks");
|
||||
|
||||
ChoiceDialog<String> dialog = new ChoiceDialog<>(choices.get(0), choices);
|
||||
dialog.setTitle("New File");
|
||||
dialog.setHeaderText("Select a type for the new file.");
|
||||
dialog.setContentText("Type:");
|
||||
dialog.initOwner(Main.mainStage);
|
||||
|
||||
dialog.getDialogPane().setMinSize(200,200);
|
||||
Optional<String> result = dialog.showAndWait();
|
||||
if (result.isPresent()){
|
||||
if (result.get().equals(choices.get(0)))
|
||||
return WorldsType.AVATAR;
|
||||
else if (result.get().equals(choices.get(1)))
|
||||
return WorldsType.WORLDSMARK;
|
||||
else return WorldsType.NULL;
|
||||
} else {
|
||||
return WorldsType.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public static void showUpdate(Version newVer) {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
assert Main.verMan != null;
|
||||
alert.setTitle("Update Dialog");
|
||||
alert.setHeaderText("A new version (v" + newVer.get() + ") of Organizer is available for download.\nYou are currently on v" + Console.getVersion() + ".");
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
ButtonType updateButton = new ButtonType("Open");
|
||||
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||
|
||||
Label label = new Label("View Changelog");
|
||||
|
||||
TextArea textArea = new TextArea(Console.changelogify(Main.verMan.getChangelog(newVer)));
|
||||
textArea.setEditable(false);
|
||||
textArea.setWrapText(true);
|
||||
|
||||
textArea.setMaxWidth(Double.MAX_VALUE);
|
||||
textArea.setMaxHeight(Double.MAX_VALUE);
|
||||
GridPane.setVgrow(textArea, Priority.ALWAYS);
|
||||
GridPane.setHgrow(textArea, Priority.ALWAYS);
|
||||
|
||||
GridPane expContent = new GridPane();
|
||||
expContent.setMaxWidth(Double.MAX_VALUE);
|
||||
expContent.add(label, 0, 0);
|
||||
expContent.add(textArea, 0, 1);
|
||||
|
||||
alert.getDialogPane().setExpandableContent(expContent);
|
||||
alert.getButtonTypes().setAll(updateButton, buttonTypeCancel);
|
||||
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if (result.get() == updateButton) {
|
||||
Console.print("Displaying webpage in native browser.", 1, ConsoleType.INFO);
|
||||
Main.hostServices.showDocument(Main.verMan.url.replace("{ver}", newVer.get()));
|
||||
} else {
|
||||
alert.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static void process() {
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle("Message");
|
||||
alert.setHeaderText(
|
||||
"For all you give me, an " + "ea" + "st" + "er" + " " + "e" + "gg" + " for you."
|
||||
);
|
||||
alert.setContentText(
|
||||
"I" + " l" + "ov" + "e" + " yo" + "u," + "DO" + "SF" + "OX" + "!"
|
||||
);
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class InvalidPersisterException extends IOException {
|
||||
|
||||
public InvalidPersisterException() {
|
||||
super();
|
||||
}
|
||||
|
||||
public InvalidPersisterException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public InvalidPersisterException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public InvalidPersisterException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
}
|
||||
705
src/main/java/org/worlio/WorldsOrganizer/Main.java
Normal file
@@ -0,0 +1,705 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import javafx.application.Application;
|
||||
import javafx.application.HostServices;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Pos;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.layout.Pane;
|
||||
import javafx.scene.layout.Priority;
|
||||
import javafx.scene.layout.VBox;
|
||||
import javafx.scene.paint.Color;
|
||||
import javafx.scene.text.*;
|
||||
import javafx.stage.FileChooser;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class Main extends Application {
|
||||
|
||||
static int debugMode = 0;
|
||||
static ConfigManager configManager;
|
||||
static VersionManager verMan;
|
||||
|
||||
static List<File> startFiles = new ArrayList<>();
|
||||
static List<WorldsTab> tabs = new ArrayList<>();
|
||||
|
||||
private TabPane tabPane;
|
||||
private static Pane statusPane;
|
||||
|
||||
public static Stage mainStage;
|
||||
static HostServices hostServices;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Console.print("Worlds Organizer v" + Console.getVersion());
|
||||
Console.print("Running on Java " + System.getProperty("java.version"));
|
||||
|
||||
configManager = new ConfigManager(new File((Console.getParent() + "/config.json")));
|
||||
|
||||
try {
|
||||
verMan = new VersionManager();
|
||||
} catch (IOException e) {
|
||||
Console.print("An IOException was encountered attempting to obtain the version.", 1, ConsoleType.ERROR);
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (debugMode < 1) debugMode = configManager.getBooleanValue(ConfigEntry.debug) ? 1 : 0;
|
||||
|
||||
Console.print("Initializing main application.", ConsoleType.INFO);
|
||||
hostServices = this.getHostServices();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
boolean doRun = true;
|
||||
for (int a = 0; a < args.length; a++) {
|
||||
String arg = args[a];
|
||||
if (arg.startsWith("--debug")) {
|
||||
try {
|
||||
debugMode = Integer.parseInt(args[a+1]);
|
||||
Console.print("Debug mode set to: " + debugMode, 1, ConsoleType.INFO);
|
||||
a++;
|
||||
} catch (NumberFormatException e) {
|
||||
debugMode = 0;
|
||||
Console.print("NumberFormatException encountered! Defaulting to 0.", 1, ConsoleType.WARNING);
|
||||
}
|
||||
} else if (arg.equals("-i") || arg.equals("--input")) {
|
||||
try {
|
||||
File newFile = new File(args[a + 1]);
|
||||
startFiles.add(newFile);
|
||||
a++;
|
||||
} catch (Exception e) {
|
||||
Console.print("Invalid file location in argument!", 0, ConsoleType.ERROR);
|
||||
}
|
||||
} else if (arg.equals("-h") || arg.equals("--help")) {
|
||||
doRun = false;
|
||||
Console.getHelp();
|
||||
break;
|
||||
} else {
|
||||
doRun = false;
|
||||
Console.print(arg + " is not a valid argument. Please use '-help' to see a list of options and arguments.", 0, ConsoleType.WARNING);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doRun) launch(args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start(final Stage stage) {
|
||||
mainStage = stage;
|
||||
mainStage.setTitle("Worlds Organizer");
|
||||
mainStage.getIcons().add(AppIcon.logo);
|
||||
|
||||
Console.print("Starting Window", 1, ConsoleType.INFO);
|
||||
|
||||
|
||||
mainStage.setOnCloseRequest(a -> {
|
||||
quit();
|
||||
});
|
||||
|
||||
|
||||
ToolBar menuBar = new ToolBar();
|
||||
|
||||
Button newFileBtn = new Button("New");
|
||||
newFileBtn.setGraphic(new ImageView(AppIcon.newFile));
|
||||
menuBar.getItems().add(newFileBtn);
|
||||
|
||||
Button openFileBtn = new Button("Open");
|
||||
openFileBtn.setGraphic(new ImageView(AppIcon.openFile));
|
||||
menuBar.getItems().add(openFileBtn);
|
||||
|
||||
Button saveFileBtn = new Button("Save");
|
||||
saveFileBtn.setGraphic(new ImageView(AppIcon.saveFile));
|
||||
menuBar.getItems().add(saveFileBtn);
|
||||
|
||||
Button saveAsFileBtn = new Button("Save As");
|
||||
saveAsFileBtn.setGraphic(new ImageView(AppIcon.saveFileAs));
|
||||
menuBar.getItems().add(saveAsFileBtn);
|
||||
|
||||
menuBar.getItems().add(new Separator());
|
||||
|
||||
Button undoBtn = new Button();
|
||||
undoBtn.setGraphic(new ImageView(AppIcon.undo));
|
||||
undoBtn.setTooltip(new Tooltip("Undo"));
|
||||
menuBar.getItems().add(undoBtn);
|
||||
|
||||
Button redoBtn = new Button();
|
||||
redoBtn.setGraphic(new ImageView(AppIcon.redo));
|
||||
redoBtn.setTooltip(new Tooltip("Redo"));
|
||||
menuBar.getItems().add(redoBtn);
|
||||
|
||||
menuBar.getItems().add(new Separator());
|
||||
|
||||
Button confBtn = new Button();
|
||||
confBtn.setTooltip(new Tooltip("Preferences"));
|
||||
confBtn.setGraphic(new ImageView(AppIcon.config));
|
||||
menuBar.getItems().add(confBtn);
|
||||
|
||||
Button quitBtn = new Button("Quit");
|
||||
quitBtn.setGraphic(new ImageView(AppIcon.quitApp));
|
||||
menuBar.getItems().add(quitBtn);
|
||||
|
||||
// Adding a tab pane
|
||||
tabPane = new TabPane();
|
||||
|
||||
Console.print("Initializing Start Page", 1, ConsoleType.INFO);
|
||||
|
||||
// This will be permanent, and be exempt from the tab values we record.
|
||||
Tab startTab = getStartPage();
|
||||
startTab.setClosable(false);
|
||||
|
||||
tabPane.getTabs().add(startTab);
|
||||
|
||||
// Assigning all the events now.
|
||||
Console.print("Assigning Events", 1, ConsoleType.INFO);
|
||||
tabPane.addEventFilter(Tab.CLOSED_EVENT, f -> {
|
||||
Console.print("Detected Tab Closed. Index " + (tabPane.getSelectionModel().getSelectedIndex() - 1) + ".", 1, ConsoleType.INFO);
|
||||
tabs.remove(tabPane.getSelectionModel().getSelectedIndex() - 1);
|
||||
});
|
||||
|
||||
// First adding the status bar
|
||||
statusPane = new VBox(new Text());
|
||||
statusPane.setPadding(new Insets(4, 4, 4, 4));
|
||||
VBox vBox = new VBox(menuBar, tabPane);
|
||||
if (configManager.getBooleanValue(ConfigEntry.status)) vBox.getChildren().add(statusPane);
|
||||
Console.print("Completed Base Window Initialization", 1, ConsoleType.INFO);
|
||||
Scene scene = new Scene(vBox, 960, 600);
|
||||
|
||||
newFileBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
if (e.isShiftDown()) {
|
||||
try {
|
||||
WorldListObject tempW = tabs.get(0).worldList;
|
||||
if (tempW.size() <= 1) {
|
||||
if (
|
||||
tempW.get(0).getName().equals(
|
||||
"D" + "F"
|
||||
) && tempW.get(0).getValue().equals(
|
||||
"6" + "/" + "2" + "7" + "/" + "2" + "0"
|
||||
)
|
||||
) {
|
||||
Console.process();
|
||||
} else newFile();
|
||||
} else newFile();
|
||||
} catch (NullPointerException | IndexOutOfBoundsException ignored) {}
|
||||
} else newFile();
|
||||
});
|
||||
|
||||
openFileBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
openFile(null);
|
||||
});
|
||||
|
||||
saveFileBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
try {
|
||||
WorldsTab tableObj = tabs.get(tabPane.getSelectionModel().getSelectedIndex() - 1);
|
||||
saveFile(tableObj, tableObj.file);
|
||||
Main.setStatusText("Saved file to '" + tableObj.file.getAbsolutePath() + "'.");
|
||||
} catch (IndexOutOfBoundsException i) {
|
||||
Console.print("IndexOutOfBoundsException encountered! Must be on file tab to save.", ConsoleType.ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
saveAsFileBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
try {
|
||||
WorldsTab tableObj = tabs.get(tabPane.getSelectionModel().getSelectedIndex() - 1);
|
||||
saveFile(tableObj);
|
||||
} catch (IndexOutOfBoundsException i) {
|
||||
Console.print("IndexOutOfBoundsException encountered! Must be on file tab to save.", ConsoleType.ERROR);
|
||||
}
|
||||
});
|
||||
|
||||
undoBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
if (tabs.size() > 0 && tabPane.getSelectionModel().getSelectedIndex() > 0) {
|
||||
WorldsTab tableObj = tabs.get(tabPane.getSelectionModel().getSelectedIndex() - 1);
|
||||
tableObj.doUndo();
|
||||
}
|
||||
});
|
||||
|
||||
redoBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
if (tabs.size() > 0 && tabPane.getSelectionModel().getSelectedIndex() > 0) {
|
||||
WorldsTab tableObj = tabs.get(tabPane.getSelectionModel().getSelectedIndex() - 1);
|
||||
tableObj.doRedo();
|
||||
}
|
||||
});
|
||||
|
||||
confBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
// This is it's own window to circumvent the issues with Buttons
|
||||
// and design on Dialog.
|
||||
|
||||
Stage confStage = new Stage();
|
||||
confStage.initOwner(mainStage);
|
||||
confStage.setTitle("Preferences");
|
||||
|
||||
Console.print("Displaying Configuration Window", 1, ConsoleType.INFO);
|
||||
|
||||
|
||||
// General Tab
|
||||
|
||||
Label channelName = new Label("Update Channel");
|
||||
channelName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label channelInfo = new Label("Channel to use for update checks and links: 'stable' will provide tested " +
|
||||
"build updates while 'beta' is more of an experimental bug-finding experience.");
|
||||
channelInfo.setWrapText(true);
|
||||
|
||||
ObservableList<String> channels =
|
||||
FXCollections.observableArrayList(ConfigManager.channels);
|
||||
|
||||
ComboBox<String> channelOption = new ComboBox(channels);
|
||||
channelOption.getSelectionModel().select(configManager.getStringValue(ConfigEntry.channel));
|
||||
HBox.setHgrow(channelOption, Priority.ALWAYS);
|
||||
|
||||
|
||||
// Appearance Tab
|
||||
|
||||
Label darkName = new Label("Use Dark Mode");
|
||||
darkName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label darkInfo = new Label("Changes the style of the application to use a basic dark theme.");
|
||||
darkInfo.setWrapText(true);
|
||||
|
||||
CheckBox darkOption = new CheckBox("Enabled");
|
||||
darkOption.setSelected(configManager.getBooleanValue(ConfigEntry.darkMode));
|
||||
darkOption.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
||||
configManager.setValue(ConfigEntry.darkMode, isSelected);
|
||||
});
|
||||
VBox.setVgrow(darkOption, Priority.ALWAYS);
|
||||
|
||||
Label statusName = new Label("Display Status Bar");
|
||||
statusName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label statusInfo = new Label("Changes the style of the application to use a basic dark theme. Requires a restart to apply.");
|
||||
statusInfo.setWrapText(true);
|
||||
|
||||
CheckBox statusOption = new CheckBox("Enabled");
|
||||
statusOption.setSelected(configManager.getBooleanValue(ConfigEntry.status));
|
||||
statusOption.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
||||
configManager.setValue(ConfigEntry.status, isSelected);
|
||||
});
|
||||
VBox.setVgrow(statusOption, Priority.ALWAYS);
|
||||
|
||||
Label toolName = new Label("Toolbar Location");
|
||||
toolName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label toolInfo = new Label("The edge to place the toolbar that holds the file tools. Default is 'LEFT'.");
|
||||
toolInfo.setWrapText(true);
|
||||
|
||||
Label toolLabel = new Label("Toolbar Location: ");
|
||||
HBox.setHgrow(toolLabel, Priority.SOMETIMES);
|
||||
|
||||
ObservableList<String> toolPos =
|
||||
FXCollections.observableArrayList(ConfigManager.toolBarPos);
|
||||
|
||||
ComboBox<String> toolPosOption = new ComboBox<>(toolPos);
|
||||
toolPosOption.getSelectionModel().select(configManager.getIntValue(ConfigEntry.toolbarPos));
|
||||
HBox.setHgrow(toolPosOption, Priority.ALWAYS);
|
||||
|
||||
Label sizeName = new Label("Icon Size");
|
||||
sizeName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label sizeInfo = new Label("Size (in pixels) of icons in the window. Requires a restart to apply.");
|
||||
sizeInfo.setWrapText(true);
|
||||
|
||||
Slider iconSizeSlider = new Slider(16, 96, configManager.getIntValue(ConfigEntry.iconSize));
|
||||
iconSizeSlider.setTooltip(new Tooltip("Set icon size for the interface icons."));
|
||||
HBox.setHgrow(iconSizeSlider, Priority.SOMETIMES);
|
||||
iconSizeSlider.setShowTickLabels(true);
|
||||
iconSizeSlider.setShowTickMarks(true);
|
||||
iconSizeSlider.setMajorTickUnit(16);
|
||||
iconSizeSlider.setMinorTickCount(1);
|
||||
iconSizeSlider.setSnapToTicks(true);
|
||||
|
||||
|
||||
// Advanced Tab
|
||||
|
||||
Label backupName = new Label("Use Backups");
|
||||
backupName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label backupInfo = new Label("Creates a backup of the file before the save process.");
|
||||
backupInfo.setWrapText(true);
|
||||
|
||||
CheckBox backupOption = new CheckBox("Enabled");
|
||||
backupOption.setSelected(configManager.getBooleanValue(ConfigEntry.fileBackup));
|
||||
backupOption.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
||||
configManager.setValue(ConfigEntry.fileBackup, isSelected);
|
||||
});
|
||||
VBox.setVgrow(backupOption, Priority.ALWAYS);
|
||||
|
||||
Label debugName = new Label("Print Debug");
|
||||
debugName.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 12));
|
||||
Label debugInfo = new Label("Prints out debug information in the commandline output. Requires a restart to apply.");
|
||||
debugInfo.setWrapText(true);
|
||||
|
||||
CheckBox debugCheck = new CheckBox("Enabled");
|
||||
debugCheck.setSelected(configManager.getBooleanValue(ConfigEntry.debug));
|
||||
debugCheck.selectedProperty().addListener((obs, wasSelected, isSelected) -> {
|
||||
configManager.setValue(ConfigEntry.debug, isSelected);
|
||||
});
|
||||
VBox.setVgrow(debugCheck, Priority.ALWAYS);
|
||||
|
||||
Button applyButton = new Button("Apply");
|
||||
applyButton.setDefaultButton(true);
|
||||
applyButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> {
|
||||
configManager.setValue(ConfigEntry.toolbarPos, toolPosOption.getValue());
|
||||
configManager.setValue(ConfigEntry.channel, channelOption.getValue());
|
||||
configManager.setValue(ConfigEntry.iconSize, (int)iconSizeSlider.getValue());
|
||||
configManager.write();
|
||||
toggleDark(scene);
|
||||
Main.setStatusText("Applied new settings.");
|
||||
});
|
||||
|
||||
Button okButton = new Button("Ok");
|
||||
okButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> {
|
||||
configManager.setValue(ConfigEntry.toolbarPos, toolPosOption.getValue());
|
||||
configManager.setValue(ConfigEntry.channel, channelOption.getValue());
|
||||
configManager.setValue(ConfigEntry.iconSize, (int)iconSizeSlider.getValue());
|
||||
configManager.write();
|
||||
toggleDark(scene);
|
||||
confStage.close();
|
||||
Main.setStatusText("Applied new settings.");
|
||||
});
|
||||
|
||||
Button cancelButton = new Button("Cancel");
|
||||
cancelButton.setCancelButton(true);
|
||||
cancelButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> {
|
||||
confStage.close();
|
||||
});
|
||||
|
||||
// Tabbing every option into their own VBox so we can have them split off in their own containers.
|
||||
// This makes it easier to add to tabs because it's just a simple declare. Also good for design.
|
||||
VBox vGeneral = new VBox(channelName, channelInfo, channelOption);
|
||||
ScrollPane general = new ScrollPane(vGeneral);
|
||||
general.setFitToWidth(true);
|
||||
Tab generalTab = new Tab("General", general);
|
||||
VBox.setVgrow(general, Priority.ALWAYS);
|
||||
vGeneral.setPadding(new Insets(10, 10, 10, 10));
|
||||
vGeneral.setSpacing(10);
|
||||
|
||||
VBox vSkin = new VBox(darkName, darkInfo, darkOption, statusName, statusInfo, statusOption,
|
||||
toolName, toolInfo, toolPosOption, sizeName, sizeInfo, iconSizeSlider);
|
||||
ScrollPane skin = new ScrollPane(vSkin);
|
||||
skin.setFitToWidth(true);
|
||||
Tab skinTab = new Tab("Appearance", skin);
|
||||
VBox.setVgrow(skin, Priority.ALWAYS);
|
||||
vSkin.setPadding(new Insets(10, 10, 10, 10));
|
||||
vSkin.setSpacing(10);
|
||||
|
||||
VBox vAdvance = new VBox(backupName, backupInfo, backupOption, debugName, debugInfo, debugCheck);
|
||||
ScrollPane advance = new ScrollPane(vAdvance);
|
||||
advance.setFitToWidth(true);
|
||||
Tab advanceTab = new Tab("Advanced", advance);
|
||||
VBox.setVgrow(advance, Priority.ALWAYS);
|
||||
vAdvance.setPadding(new Insets(10, 10, 10, 10));
|
||||
vAdvance.setSpacing(10);
|
||||
|
||||
TabPane prefPane = new TabPane(generalTab, skinTab, advanceTab);
|
||||
VBox.setVgrow(prefPane, Priority.ALWAYS);
|
||||
prefPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
|
||||
|
||||
general.maxWidthProperty().bind(prefPane.widthProperty());
|
||||
skin.maxWidthProperty().bind(prefPane.widthProperty());
|
||||
advance.maxWidthProperty().bind(prefPane.widthProperty());
|
||||
|
||||
ButtonBar bBar = new ButtonBar();
|
||||
bBar.getButtons().addAll(applyButton, okButton, cancelButton);
|
||||
bBar.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
confStage.setMinWidth(350);
|
||||
confStage.setMinHeight(250);
|
||||
|
||||
confStage.setScene(new Scene(new VBox(prefPane, bBar), 350, 350));
|
||||
confStage.show();
|
||||
});
|
||||
|
||||
quitBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
e.consume();
|
||||
quit();
|
||||
});
|
||||
|
||||
VBox.setVgrow(tabPane, Priority.ALWAYS);
|
||||
|
||||
toggleDark(scene);
|
||||
|
||||
Console.print("Scene Prepared", 1, ConsoleType.INFO);
|
||||
mainStage.setScene(scene);
|
||||
mainStage.show();
|
||||
Console.print("Displaying Main Window", 1, ConsoleType.INFO);
|
||||
|
||||
// Going through files set up on command-line arguments.
|
||||
Console.print("Iterating through argument files", 1, ConsoleType.INFO);
|
||||
if (startFiles != null && startFiles.size() > 0) {
|
||||
try {
|
||||
for (File start : startFiles) {
|
||||
if (start.exists()) openFile(start);
|
||||
else Console.print("Unable to open file: File Not Found:\n'" + start.getPath() + "'", ConsoleType.ERROR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Console.print("An unknown error occurred attempting to open argument files.", 1, ConsoleType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void setStatusText(String message) {
|
||||
statusPane.getChildren().set(0, new Text(message));
|
||||
|
||||
// 2.5 Seconds later, the text will disappear. Makes it look neater and also makes sure you
|
||||
// aren't frozen I guess.
|
||||
Task<Void> sleeper = new Task<Void>() {
|
||||
@Override
|
||||
protected Void call() {
|
||||
try {
|
||||
Thread.sleep(2500);
|
||||
} catch (InterruptedException e) {
|
||||
statusPane = new VBox(new Text());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
sleeper.setOnSucceeded(event -> statusPane.getChildren().set(0, new Text()));
|
||||
new Thread(sleeper).start();
|
||||
}
|
||||
|
||||
private void toggleDark(Scene curScene) {
|
||||
if (configManager.getBooleanValue(ConfigEntry.darkMode)) curScene.getStylesheets().add("dark.css");
|
||||
else curScene.getStylesheets().remove("dark.css");
|
||||
}
|
||||
|
||||
public Tab getStartPage() {
|
||||
VBox mainBox = new VBox();
|
||||
|
||||
// Styling fancy texts.
|
||||
ImageView logoView = new ImageView(AppIcon.logo);
|
||||
Text nameTxt = new Text("Worlds Organizer v" + Console.getVersion());
|
||||
nameTxt.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 20));
|
||||
Text buildTxt = new Text("Build Date: " + Console.getDate());
|
||||
buildTxt.setFont(Font.font("Verdana", FontWeight.NORMAL, FontPosture.REGULAR, 12));
|
||||
buildTxt.setFill(Color.GRAY);
|
||||
Text devTxt = new Text("Developed by Worlio LLC");
|
||||
devTxt.setFont(Font.font("Verdana", FontWeight.MEDIUM, FontPosture.REGULAR, 12));
|
||||
|
||||
logoView.setPreserveRatio(true);
|
||||
logoView.fitHeightProperty().bind(mainBox.heightProperty().multiply(0.5));
|
||||
mainBox.setAlignment(Pos.CENTER);
|
||||
|
||||
Button updateButton = new Button("Check for Updates");
|
||||
updateButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> {
|
||||
boolean isUpdatable;
|
||||
try {
|
||||
// Simply restarting the manager so it gets everything fresh.
|
||||
// Simple yet effective at what we want, without issues.
|
||||
verMan = new VersionManager();
|
||||
isUpdatable = verMan.hasUpdate();
|
||||
if (isUpdatable) {
|
||||
Console.print("Update detected! Showing dialog.", ConsoleType.INFO);
|
||||
verMan.pushUpdate();
|
||||
} else Console.print("No updates available.", ConsoleType.INFO);
|
||||
} catch (IOException e) {
|
||||
Console.print("Could not check for updates!", ConsoleType.ERROR);
|
||||
isUpdatable = false;
|
||||
}
|
||||
if (!isUpdatable) Dialog.showError("Update Check", "No new updates are available.");
|
||||
});
|
||||
|
||||
Button changelogButton = new Button("What's new?");
|
||||
changelogButton.addEventFilter(MouseEvent.MOUSE_CLICKED, a -> {
|
||||
Stage changelogStage = new Stage();
|
||||
changelogStage.initOwner(mainStage);
|
||||
changelogStage.setTitle("What's new?");
|
||||
|
||||
VBox changesBox = new VBox();
|
||||
|
||||
// Reading the json file remotely, and then looking through every single value in the list.
|
||||
// It's simple text, so it makes it easy to parse and style.
|
||||
|
||||
for (Map.Entry<?, ?> vC : ((Map<?, ?>)((Map<?, ?>)verMan.json.get("versions")).get(configManager.getStringValue(ConfigEntry.channel))).entrySet()) {
|
||||
|
||||
// UPDATES UPDATES UPDATES
|
||||
if (new Version((String)vC.getKey()).equals(new Version(Console.getVersion()))) {
|
||||
Text channel = new Text("Current Version");
|
||||
channel.setFont(Font.font("Verdana", FontWeight.LIGHT, FontPosture.ITALIC, 12));
|
||||
changesBox.getChildren().add(channel);
|
||||
}
|
||||
|
||||
Text version = new Text((String)vC.getKey());
|
||||
version.setFont(Font.font("Verdana", FontWeight.BOLD, FontPosture.REGULAR, 14));
|
||||
changesBox.getChildren().add(version);
|
||||
for (String line : verMan.getChangelog(new Version((String)vC.getKey()))) {
|
||||
Text lineTxt = new Text(" - " + line);
|
||||
lineTxt.wrappingWidthProperty().bind(changesBox.prefWidthProperty().multiply(0.95));
|
||||
changesBox.getChildren().add(lineTxt);
|
||||
}
|
||||
changesBox.getChildren().add(new Separator());
|
||||
}
|
||||
changesBox.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
// Organize it nicely within a small ScrollPane.
|
||||
// It took forever to get the text to wrap so this works.
|
||||
ScrollPane changesPane = new ScrollPane(changesBox);
|
||||
VBox.setVgrow(changesPane, Priority.ALWAYS);
|
||||
changesPane.prefWidthProperty().bind(changelogStage.widthProperty());
|
||||
changesPane.setFitToWidth(true);
|
||||
|
||||
changesBox.prefWidthProperty().bind(changesPane.widthProperty());
|
||||
|
||||
Button cancelButton = new Button("Close");
|
||||
cancelButton.setCancelButton(true);
|
||||
cancelButton.addEventFilter(MouseEvent.MOUSE_CLICKED, (e) -> changelogStage.close());
|
||||
|
||||
ButtonBar bBar = new ButtonBar();
|
||||
bBar.getButtons().addAll(cancelButton);
|
||||
bBar.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
changelogStage.setMinWidth(450);
|
||||
changelogStage.setMinHeight(400);
|
||||
|
||||
changelogStage.setScene(new Scene(new VBox(changesPane, bBar), 450, 400));
|
||||
changelogStage.show();
|
||||
});
|
||||
|
||||
HBox bBar = new HBox(changelogButton, updateButton);
|
||||
bBar.setAlignment(Pos.CENTER);
|
||||
bBar.setSpacing(10);
|
||||
bBar.setPadding(new Insets(10, 10, 10, 10));
|
||||
|
||||
mainBox.getChildren().addAll(logoView, nameTxt, buildTxt, devTxt, bBar);
|
||||
return new Tab("Start Page", mainBox);
|
||||
}
|
||||
|
||||
void newFile() {
|
||||
// Essentially a bare bones way of opening a file without the file.
|
||||
|
||||
WorldsTab tableObj = new WorldsTab();
|
||||
WorldsType newType = Dialog.newFileList();
|
||||
if (newType != WorldsType.NULL) {
|
||||
Console.print("Creating a new tab", 1, ConsoleType.INFO);
|
||||
|
||||
Tab tab = tableObj.getTab(newType);
|
||||
|
||||
tabPane.getTabs().add(tab);
|
||||
tabs.add(tableObj);
|
||||
|
||||
Main.setStatusText("Opened new tab.");
|
||||
|
||||
tabPane.getSelectionModel().select(tabPane.getTabs().size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void openFile(File file) {
|
||||
File openedFile;
|
||||
if (file == null) {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Open File");
|
||||
fileChooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("All Files", "*"),
|
||||
new FileChooser.ExtensionFilter("All Supported Formats", "*.avatars", "*.worldsmarks", "*.organizer-bkup"),
|
||||
new FileChooser.ExtensionFilter("Gamma Avatars (*.avatars)", "*.avatars"),
|
||||
new FileChooser.ExtensionFilter("Gamma WorldsMarks (*.worldsmarks)", "*.worldsmarks")
|
||||
);
|
||||
openedFile = fileChooser.showOpenDialog(mainStage);
|
||||
} else {
|
||||
openedFile = file;
|
||||
}
|
||||
|
||||
if (openedFile != null) {
|
||||
WorldsTab tableObj = new WorldsTab();
|
||||
Tab tab = tableObj.getTab(openedFile);
|
||||
|
||||
if (tab != null) {
|
||||
Main.setStatusText("Opened file '" + openedFile.getAbsolutePath() + "'.");
|
||||
|
||||
tabPane.getTabs().add(tab);
|
||||
tabs.add(tableObj);
|
||||
|
||||
tabPane.getSelectionModel().select(tabPane.getTabs().size() - 1);
|
||||
} else {
|
||||
Console.print("InvalidPersisterFile encountered! File is not a supported format.", ConsoleType.ERROR);
|
||||
Dialog.showError("Invalid File!", "File selected is not a valid Persister format.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void saveFile(WorldsTab tab) {
|
||||
saveFile(tab, null);
|
||||
}
|
||||
|
||||
void saveFile(WorldsTab tab, File file) {
|
||||
File thisFile;
|
||||
if (file == null) {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Save As File");
|
||||
fileChooser.getExtensionFilters().addAll(
|
||||
new FileChooser.ExtensionFilter("Gamma Avatars (*.avatars)", "*.avatars"),
|
||||
new FileChooser.ExtensionFilter("Gamma WorldsMarks (*.worldsmarks)", "*.worldsmarks")
|
||||
);
|
||||
fileChooser.setInitialFileName("gamma");
|
||||
thisFile = fileChooser.showSaveDialog(mainStage);
|
||||
|
||||
if (thisFile != null) {
|
||||
switch (fileChooser.getSelectedExtensionFilter().getExtensions().get(0)) {
|
||||
default:
|
||||
case "*.avatars":
|
||||
tab.worldList.classType = WorldsType.AVATAR;
|
||||
break;
|
||||
case "*.worldsmarks":
|
||||
tab.worldList.classType = WorldsType.WORLDSMARK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
thisFile = file;
|
||||
}
|
||||
|
||||
if (thisFile != null) {
|
||||
try {
|
||||
Saver saver = new Saver(thisFile);
|
||||
saver.save(tab.worldList);
|
||||
tab.setSaved(true);
|
||||
tab.update(thisFile);
|
||||
Main.setStatusText("Saved file to '" + thisFile.getAbsolutePath() + "'.");
|
||||
} catch (IOException e) {
|
||||
Console.print("Unable to save file: " + thisFile.getAbsolutePath(), ConsoleType.ERROR);
|
||||
Dialog.showException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void quit() {
|
||||
boolean askForSure = false;
|
||||
for (WorldsTab t : tabs) {
|
||||
if (!t.getSaved()) {
|
||||
askForSure = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (askForSure) {
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
alert.setTitle("Quit");
|
||||
alert.setHeaderText("Are you sure you want to quit?");
|
||||
alert.setContentText("You have unsaved changes. Quitting now will lose your progress.");
|
||||
|
||||
ButtonType dontSaveButton = new ButtonType("Discard Changes");
|
||||
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||
|
||||
alert.getButtonTypes().setAll(dontSaveButton, buttonTypeCancel);
|
||||
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if (result.get() == dontSaveButton) {
|
||||
mainStage.close();
|
||||
} else {
|
||||
alert.close();
|
||||
}
|
||||
} else {
|
||||
mainStage.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/main/java/org/worlio/WorldsOrganizer/MarkObject.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public class MarkObject implements WorldList {
|
||||
|
||||
private String name;
|
||||
private String value;
|
||||
|
||||
MarkObject(String name, String value) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String code) {
|
||||
this.value = code;
|
||||
}
|
||||
}
|
||||
101
src/main/java/org/worlio/WorldsOrganizer/Restorer.java
Normal file
@@ -0,0 +1,101 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class Restorer {
|
||||
|
||||
DataInputStream dis;
|
||||
|
||||
File file;
|
||||
public WorldListObject listObj;
|
||||
|
||||
private int oID;
|
||||
|
||||
Restorer(String path) {
|
||||
new Restorer(new File(path));
|
||||
}
|
||||
|
||||
Restorer(File file) {
|
||||
Console.print("Initialized Restorer", 1, ConsoleType.INFO);
|
||||
this.file = file;
|
||||
try {
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
dis = new DataInputStream(fis);
|
||||
Console.print("Restorer file set as '" + file.getAbsolutePath() + "'", 1, ConsoleType.INFO);
|
||||
} catch (IOException e) {
|
||||
Console.print("IOException reading file: '" + file.getAbsolutePath() + "'", ConsoleType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
WorldListObject read() throws IOException {
|
||||
if (dis == null) {
|
||||
throw new InvalidPersisterException();
|
||||
}
|
||||
|
||||
try {
|
||||
if (!readString().equals("PERSISTER Worlds, Inc.")) { // Persister Header
|
||||
throw new InvalidPersisterException();
|
||||
} else {
|
||||
int pVersion = readInt(); // Persister Version
|
||||
Console.print("Persister Version detected: " + pVersion, 1, ConsoleType.INFO);
|
||||
if (pVersion != 7) Console.print("Version not supported! Issues may occur!", ConsoleType.WARNING);
|
||||
|
||||
int count = readInt(); // Vector Count
|
||||
|
||||
readInt(); // Class ID
|
||||
return readVector(count);
|
||||
}
|
||||
} catch (NullPointerException e) {
|
||||
throw new InvalidPersisterException();
|
||||
}
|
||||
}
|
||||
|
||||
private WorldListObject readVector(int count) throws IOException {
|
||||
Console.print("Starting read of '" + file.getPath() + "'", 1, ConsoleType.INFO);
|
||||
|
||||
listObj = new WorldListObject();
|
||||
|
||||
oID = readInt(); // Object ID
|
||||
String typeText = readString(); // Class Name
|
||||
listObj.classType = WorldsType.valueOfClass(typeText);
|
||||
if (listObj.classType != null) {
|
||||
Console.print("ClassName read as '" + typeText + "'. Setting type to '" + WorldsType.valueOfClass(typeText) + "'.", 2, ConsoleType.DEBUG);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i > 0) readInt();
|
||||
readInt(); // Version
|
||||
WorldList newData = null;
|
||||
if (listObj.classType == WorldsType.AVATAR) newData = new AvatarObject(readString(), readString());
|
||||
else if (listObj.classType == WorldsType.WORLDSMARK) newData = new MarkObject(readString(), readString());
|
||||
assert newData != null;
|
||||
listObj.add(newData);
|
||||
Console.print("Created WorldList item: { name: '" + newData.getName() + "', value: '" + newData.getValue() + "' }", 2, ConsoleType.DEBUG);
|
||||
Console.print("Added new WorldList item to WorldListObject", 1, ConsoleType.DEBUG);
|
||||
}
|
||||
assert readString().equals("END PERSISTER");
|
||||
}
|
||||
|
||||
return listObj;
|
||||
}
|
||||
|
||||
String readString() throws IOException {
|
||||
if (readBoolean()) {
|
||||
return null;
|
||||
} else {
|
||||
return dis.readUTF();
|
||||
}
|
||||
}
|
||||
|
||||
int readInt() throws IOException {
|
||||
return dis.readInt();
|
||||
}
|
||||
|
||||
byte readByte() throws IOException {
|
||||
return dis.readByte();
|
||||
}
|
||||
|
||||
boolean readBoolean() throws IOException {
|
||||
return dis.readBoolean();
|
||||
}
|
||||
|
||||
}
|
||||
86
src/main/java/org/worlio/WorldsOrganizer/Saver.java
Normal file
@@ -0,0 +1,86 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
|
||||
public class Saver {
|
||||
|
||||
DataOutputStream dis;
|
||||
|
||||
File file;
|
||||
|
||||
Saver(File file) throws IOException {
|
||||
boolean doBackup = Main.configManager.getBooleanValue(ConfigEntry.fileBackup);
|
||||
Console.print("Initialized Saver", 1, ConsoleType.INFO);
|
||||
this.file = file;
|
||||
File backupFile = new File(file.getAbsolutePath() + ".organizer-bkup");
|
||||
try {
|
||||
if (file.exists() && !doBackup) {
|
||||
Console.print("File location already exists! Creating backup at " + backupFile.getAbsolutePath(), ConsoleType.WARNING);
|
||||
Files.copy(Paths.get(file.getAbsolutePath()), Paths.get(backupFile.getAbsolutePath()), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Console.print("IOException occurred during file backup!", ConsoleType.ERROR);
|
||||
Dialog.showError("Unable to create backup!", "Saving will try and continue but might corrupt your files if it fails.");
|
||||
}
|
||||
|
||||
try {
|
||||
FileOutputStream fis = new FileOutputStream(file);
|
||||
dis = new DataOutputStream(fis);
|
||||
} catch (IOException e) {
|
||||
Console.print("Couldn't write to file!");
|
||||
Dialog.showException(e);
|
||||
}
|
||||
writeString("PERSISTER Worlds, Inc."); // Persister header
|
||||
writeInt(7); // Persister version
|
||||
|
||||
}
|
||||
|
||||
public void save(WorldListObject objects) throws IOException {
|
||||
int count = objects.size();
|
||||
writeInt(count);
|
||||
writeInt(459);
|
||||
int objID = 8782;
|
||||
writeInt(objID);
|
||||
writeString(objects.classType.name);
|
||||
Console.print("Saving as '" + objects.classType.name + "'", 2, ConsoleType.DEBUG);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (i > 0) {
|
||||
writeInt(460 + i);
|
||||
writeInt(objID);
|
||||
}
|
||||
else writeInt(1);
|
||||
writeString(objects.get(i).getName());
|
||||
writeString(objects.get(i).getValue());
|
||||
Console.print("Saved WorldList item to file: { name: '" + objects.get(i).getName() + "', value: '" + objects.get(i).getValue() + "' }", 2, ConsoleType.DEBUG);
|
||||
}
|
||||
writeString("END PERSISTER");
|
||||
}
|
||||
|
||||
void writeString(String s) throws IOException {
|
||||
if (!s.isEmpty()) {
|
||||
writeBoolean(false);
|
||||
dis.writeUTF(s);
|
||||
} else {
|
||||
writeBoolean(true);
|
||||
}
|
||||
}
|
||||
|
||||
void writeInt(int i) throws IOException {
|
||||
dis.writeInt(i);
|
||||
}
|
||||
|
||||
void writeByte(byte b) throws IOException {
|
||||
dis.writeByte(b);
|
||||
}
|
||||
|
||||
void writeBoolean(boolean b) throws IOException {
|
||||
dis.writeBoolean(b);
|
||||
}
|
||||
|
||||
}
|
||||
49
src/main/java/org/worlio/WorldsOrganizer/Version.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public class Version implements Comparable<Version> {
|
||||
|
||||
private String version;
|
||||
|
||||
public final String get() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public Version(String version) {
|
||||
if (version != null) {
|
||||
if (!version.matches("[0-9]+(\\.[0-9]+)*")) throw new IllegalArgumentException("Invalid version format");
|
||||
version = version.replace("-dev", "");
|
||||
} else throw new IllegalArgumentException("Version can not be null");
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Version that) {
|
||||
if(that == null) return 1;
|
||||
String[] thisParts = this.get().split("\\.");
|
||||
String[] thatParts = that.get().split("\\.");
|
||||
int length = Math.max(thisParts.length, thatParts.length);
|
||||
for(int i = 0; i < length; i++) {
|
||||
int thisPart = i < thisParts.length ?
|
||||
Integer.parseInt(thisParts[i]) : 0;
|
||||
int thatPart = i < thatParts.length ?
|
||||
Integer.parseInt(thatParts[i]) : 0;
|
||||
if(thisPart < thatPart)
|
||||
return -1;
|
||||
if(thisPart > thatPart)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if(this == that)
|
||||
return true;
|
||||
if(that == null)
|
||||
return false;
|
||||
if(this.getClass() != that.getClass())
|
||||
return false;
|
||||
return this.compareTo((Version) that) == 0;
|
||||
}
|
||||
|
||||
}
|
||||
71
src/main/java/org/worlio/WorldsOrganizer/VersionManager.java
Normal file
@@ -0,0 +1,71 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import com.fasterxml.jackson.databind.json.JsonMapper;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class VersionManager {
|
||||
|
||||
String url;
|
||||
public Version currentVersion = new Version(Console.getVersion());
|
||||
public Version newVersion;
|
||||
static JsonMapper mapper = new JsonMapper();
|
||||
Map<?, ?> json;
|
||||
int format;
|
||||
|
||||
private boolean isValid() {
|
||||
return format == 2;
|
||||
}
|
||||
|
||||
VersionManager() throws IOException {
|
||||
json = readJsonFromUrl(Main.configManager.getStringValue(ConfigEntry.updateURL));
|
||||
format = (int)json.get("format");
|
||||
if (!isValid()) throw new IOException("Invalid JSON Update format: Format Version is not 2");
|
||||
url = (String) json.get("url");
|
||||
Map<?, ?> updates = (Map<?, ?>) json.get("versions");
|
||||
LinkedHashMap<?, ?> ver = (LinkedHashMap<?, ?>) updates.get(Main.configManager.getStringValue(ConfigEntry.channel));
|
||||
newVersion = new Version((String)ver.keySet().toArray()[0]);
|
||||
}
|
||||
|
||||
public boolean hasUpdate() {
|
||||
if (!isValid()) return false;
|
||||
return newVersion.compareTo(currentVersion) >= 1;
|
||||
}
|
||||
|
||||
public void pushUpdate() {
|
||||
if (hasUpdate() && isValid()) {
|
||||
Dialog.showUpdate(newVersion);
|
||||
} else Console.print("No new updates available.");
|
||||
}
|
||||
|
||||
public List<String> getChangelog(Version ver) {
|
||||
if (!isValid()) return new ArrayList<>();
|
||||
|
||||
// God is horrified, and he has every right to be.
|
||||
return (List<String>)((LinkedHashMap<?, ?>) ((Map<?,?>)json.get("versions")).get(Main.configManager.getStringValue(ConfigEntry.channel))).get(ver.get());
|
||||
}
|
||||
|
||||
private static String readAll(Reader rd) throws IOException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int cp;
|
||||
while ((cp = rd.read()) != -1) {
|
||||
sb.append((char) cp);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static Map<?,?> readJsonFromUrl(String url) throws IOException {
|
||||
try (InputStream is = new URL(url).openStream()) {
|
||||
BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
|
||||
String jsonText = readAll(rd);
|
||||
return mapper.readValue(jsonText, Map.class);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
13
src/main/java/org/worlio/WorldsOrganizer/WorldList.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public interface WorldList {
|
||||
|
||||
void setName(String name);
|
||||
|
||||
String getName();
|
||||
|
||||
void setValue(String value);
|
||||
|
||||
String getValue();
|
||||
|
||||
}
|
||||
159
src/main/java/org/worlio/WorldsOrganizer/WorldListObject.java
Normal file
@@ -0,0 +1,159 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
enum WorldsType {
|
||||
NULL(""),
|
||||
AVATAR("NET.worlds.console.SavedAvMenuItem"),
|
||||
WORLDSMARK("NET.worlds.console.BookmarkMenuItem"),
|
||||
LIBRARY("NET.worlds.scape.Library");
|
||||
|
||||
public final String name;
|
||||
|
||||
WorldsType(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public static WorldsType valueOfClass(String name) {
|
||||
for (WorldsType e : values()) {
|
||||
if (e.name.equals(name)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public class WorldListObject implements Cloneable {
|
||||
|
||||
public WorldsType classType = null;
|
||||
private List<WorldList> values = new ArrayList<>();
|
||||
|
||||
public WorldListObject clone() {
|
||||
try {
|
||||
return (WorldListObject) super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
WorldListObject() {
|
||||
}
|
||||
|
||||
public void determineClassType(String className) {
|
||||
switch (className) {
|
||||
default:
|
||||
break;
|
||||
case "NET.worlds.console.SavedAvMenuItem":
|
||||
classType = WorldsType.AVATAR;
|
||||
break;
|
||||
case "NET.worlds.console.BookmarkMenuItem":
|
||||
classType = WorldsType.WORLDSMARK;
|
||||
break;
|
||||
case "NET.worlds.scape.Library":
|
||||
classType = WorldsType.LIBRARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public List<WorldList> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(List<WorldList> values) {
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return values.size();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return values.isEmpty();
|
||||
}
|
||||
|
||||
public boolean contains(WorldList o) {
|
||||
return values.contains(o);
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return values.iterator();
|
||||
}
|
||||
|
||||
public WorldList[] toArray() {
|
||||
return values.toArray(new WorldList[0]);
|
||||
}
|
||||
|
||||
public boolean add(WorldList o) {
|
||||
return values.add(o);
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
return values.remove(o);
|
||||
}
|
||||
|
||||
public boolean addAll(Collection collection) {
|
||||
return values.addAll(collection);
|
||||
}
|
||||
|
||||
public boolean addAll(int i, Collection collection) {
|
||||
return values.addAll(i, collection);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
values = new ArrayList<>();
|
||||
}
|
||||
|
||||
public WorldList get(int i) {
|
||||
return values.get(i);
|
||||
}
|
||||
|
||||
public WorldList set(int i, WorldList o) {
|
||||
return values.set(i, o);
|
||||
}
|
||||
|
||||
public void add(int i, WorldList o) {
|
||||
values.add(i, o);
|
||||
}
|
||||
|
||||
public WorldList remove(int i) {
|
||||
return values.remove(i);
|
||||
}
|
||||
|
||||
public int indexOf(WorldList o) {
|
||||
return values.indexOf(o);
|
||||
}
|
||||
|
||||
public int lastIndexOf(WorldList o) {
|
||||
return values.lastIndexOf(o);
|
||||
}
|
||||
|
||||
public ListIterator listIterator() {
|
||||
return values.listIterator();
|
||||
}
|
||||
|
||||
public ListIterator listIterator(int i) {
|
||||
return values.listIterator(i);
|
||||
}
|
||||
|
||||
public List subList(int i, int i1) {
|
||||
return values.subList(i, i1);
|
||||
}
|
||||
|
||||
public boolean retainAll(Collection collection) {
|
||||
return values.retainAll(collection);
|
||||
}
|
||||
|
||||
public boolean removeAll(Collection collection) {
|
||||
return values.removeAll(collection);
|
||||
}
|
||||
|
||||
public boolean containsAll(Collection collection) {
|
||||
return values.containsAll(collection);
|
||||
}
|
||||
|
||||
public WorldList[] toArray(WorldList[] lists) {
|
||||
return values.toArray(lists);
|
||||
}
|
||||
}
|
||||
53
src/main/java/org/worlio/WorldsOrganizer/WorldTableItem.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public class WorldTableItem implements WorldList {
|
||||
private int index;
|
||||
private String name;
|
||||
private String value;
|
||||
private String status;
|
||||
|
||||
WorldTableItem(int i, String n, String v) {
|
||||
index = i;
|
||||
name = n;
|
||||
value = v;
|
||||
}
|
||||
|
||||
WorldTableItem(int i, String n, String v, boolean s) {
|
||||
index = i;
|
||||
name = n;
|
||||
value = v;
|
||||
status = (s ? "PASS" : "FAIL");
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
public class WorldsOrganizer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Main.main(args);
|
||||
}
|
||||
|
||||
}
|
||||
930
src/main/java/org/worlio/WorldsOrganizer/WorldsTab.java
Normal file
@@ -0,0 +1,930 @@
|
||||
package org.worlio.WorldsOrganizer;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.concurrent.Task;
|
||||
import javafx.event.Event;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.scene.control.cell.TextFieldTableCell;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.*;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.text.FontPosture;
|
||||
import javafx.scene.text.FontWeight;
|
||||
import javafx.scene.text.Text;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class WorldsTab {
|
||||
|
||||
File file;
|
||||
|
||||
private Tab tab = null;
|
||||
Control content = null;
|
||||
Pane mainPane;
|
||||
|
||||
private boolean showingFinder = false;
|
||||
private boolean modified = false;
|
||||
|
||||
WorldListObject worldList = new WorldListObject();
|
||||
|
||||
private final CommandStack commandStack = new CommandStack();
|
||||
|
||||
public WorldsTab() {
|
||||
}
|
||||
|
||||
public Tab getTab(File file) {
|
||||
return getTab(WorldsType.NULL, file);
|
||||
}
|
||||
|
||||
public Tab getTab(WorldsType type) {
|
||||
return getTab(type, null);
|
||||
}
|
||||
|
||||
public Tab getTab(WorldsType type, File file) {
|
||||
if (tab != null) {
|
||||
return tab;
|
||||
} else {
|
||||
Restorer restorer;
|
||||
if (file != null) {
|
||||
this.file = file;
|
||||
try {
|
||||
restorer = new Restorer(file);
|
||||
worldList = restorer.read();
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
assert type != null;
|
||||
worldList.classType = type;
|
||||
worldList.add(createItem(type));
|
||||
}
|
||||
|
||||
Tab tab;
|
||||
switch (worldList.classType) {
|
||||
default:
|
||||
tab = new Tab(); break;
|
||||
case AVATAR: case WORLDSMARK:
|
||||
tab = new Tab(generateTitle(), getWorldList()); break;
|
||||
}
|
||||
this.tab = tab;
|
||||
|
||||
update();
|
||||
|
||||
tab.setOnCloseRequest(event -> {
|
||||
Console.print("Performing tab close", 1, ConsoleType.INFO);
|
||||
event.consume();
|
||||
quitTab();
|
||||
});
|
||||
|
||||
return tab;
|
||||
}
|
||||
}
|
||||
|
||||
public Pane getWorldList() {
|
||||
if (mainPane != null) {
|
||||
return mainPane;
|
||||
} else {
|
||||
content = new TableView<WorldList>();
|
||||
((TableView<?>)content).setEditable(true);
|
||||
|
||||
ToolBar toolBar = new ToolBar();
|
||||
|
||||
Console.print("Tab initialized", 1, ConsoleType.INFO);
|
||||
|
||||
Button addBtn = new Button();
|
||||
addBtn.setTooltip(new Tooltip("Add Value"));
|
||||
addBtn.setGraphic(new ImageView(AppIcon.add));
|
||||
toolBar.getItems().add(addBtn);
|
||||
|
||||
addBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
int tabIndex = Main.tabs.indexOf(this);
|
||||
|
||||
if (tabIndex >= 0) {
|
||||
this.addItem();
|
||||
this.setFocus(((TableView<?>)content).getItems().size() - 1);
|
||||
|
||||
Main.tabs.set(tabIndex, this);
|
||||
}
|
||||
});
|
||||
|
||||
Button delBtn = new Button();
|
||||
delBtn.setTooltip(new Tooltip("Delete Value"));
|
||||
delBtn.setGraphic(new ImageView(AppIcon.remove));
|
||||
toolBar.getItems().add(delBtn);
|
||||
|
||||
delBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
int tabIndex = Main.tabs.indexOf(this);
|
||||
|
||||
if (tabIndex >= 0) {
|
||||
int index = ((TableView<?>)content).getSelectionModel().getFocusedIndex();
|
||||
this.deleteItem(index);
|
||||
this.setFocus(index < ((TableView<?>)content).getItems().size() ? index : index - 1);
|
||||
|
||||
Main.tabs.set(tabIndex, this);
|
||||
}
|
||||
});
|
||||
|
||||
Button mupBtn = new Button();
|
||||
mupBtn.setTooltip(new Tooltip("Move Value Up"));
|
||||
mupBtn.setGraphic(new ImageView(AppIcon.moveUp));
|
||||
toolBar.getItems().add(mupBtn);
|
||||
|
||||
mupBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
int tabIndex = Main.tabs.indexOf(this);
|
||||
|
||||
if (tabIndex >= 0) {
|
||||
int index = ((TableView<?>)content).getSelectionModel().getFocusedIndex();
|
||||
this.moveValue(index, -1);
|
||||
this.setFocus(index - 1);
|
||||
|
||||
Main.tabs.set(tabIndex, this);
|
||||
}
|
||||
});
|
||||
|
||||
Button mdwBtn = new Button();
|
||||
mdwBtn.setTooltip(new Tooltip("Move Value Down"));
|
||||
mdwBtn.setGraphic(new ImageView(AppIcon.moveDown));
|
||||
toolBar.getItems().add(mdwBtn);
|
||||
|
||||
mdwBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
int tabIndex = Main.tabs.indexOf(this);
|
||||
|
||||
if (tabIndex >= 0) {
|
||||
int index = ((TableView<?>)content).getSelectionModel().getFocusedIndex();
|
||||
this.moveValue(index, 1);
|
||||
this.setFocus(index + 1);
|
||||
|
||||
Main.tabs.set(tabIndex, this);
|
||||
}
|
||||
});
|
||||
|
||||
toolBar.getItems().add(new Separator());
|
||||
|
||||
Button findBtn = new Button();
|
||||
findBtn.setTooltip(new Tooltip("Find/Replace"));
|
||||
findBtn.setGraphic(new ImageView(AppIcon.findReplace));
|
||||
toolBar.getItems().add(findBtn);
|
||||
|
||||
VBox findingBox = getFindPane();
|
||||
VBox.setVgrow(findingBox, Priority.ALWAYS);
|
||||
findingBox.setVisible(false);
|
||||
findingBox.setManaged(false);
|
||||
|
||||
findBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
Console.print("Toggled Find/Replace pane", 1, ConsoleType.INFO);
|
||||
findingBox.setManaged(!showingFinder);
|
||||
findingBox.setVisible(!showingFinder);
|
||||
showingFinder = !showingFinder;
|
||||
});
|
||||
|
||||
Button checkBtn = new Button();
|
||||
checkBtn.setTooltip(new Tooltip("Link Checker"));
|
||||
checkBtn.setGraphic(new ImageView(AppIcon.linkCheck));
|
||||
toolBar.getItems().add(checkBtn);
|
||||
|
||||
checkBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
Console.print("Beginning Link Checker", 1, ConsoleType.INFO);
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.getDialogPane().setMinWidth(600);
|
||||
alert.setResizable(true);
|
||||
alert.setTitle("Link Checker");
|
||||
alert.setHeaderText("Checking Links...");
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
TableView<WorldTableItem> checkTable = new TableView<>();
|
||||
checkTable.setEditable(false);
|
||||
|
||||
checkTable.setMaxWidth(Double.MAX_VALUE);
|
||||
checkTable.setMaxHeight(Double.MAX_VALUE);
|
||||
GridPane.setVgrow(checkTable, Priority.ALWAYS);
|
||||
GridPane.setHgrow(checkTable, Priority.ALWAYS);
|
||||
|
||||
TableColumn<WorldTableItem, Integer> checkIndexColumn = new TableColumn<>("#");
|
||||
checkIndexColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.05));
|
||||
checkIndexColumn.setCellValueFactory(new PropertyValueFactory<>("index"));
|
||||
|
||||
TableColumn<WorldTableItem, String> checkLabelColumn = new TableColumn<>("Label");
|
||||
checkLabelColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.4));
|
||||
checkLabelColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
|
||||
|
||||
TableColumn<WorldTableItem, String> checkValueColumn = new TableColumn<>("Value");
|
||||
checkValueColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.4));
|
||||
checkValueColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
|
||||
|
||||
TableColumn<WorldTableItem, String> checkStatusColumn = new TableColumn<>("Status");
|
||||
checkStatusColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.1));
|
||||
checkStatusColumn.setCellValueFactory(new PropertyValueFactory<>("status"));
|
||||
|
||||
checkTable.getColumns().addAll(checkIndexColumn, checkLabelColumn, checkValueColumn, checkStatusColumn);
|
||||
|
||||
alert.getDialogPane().setContent(checkTable);
|
||||
|
||||
alert.initOwner(Main.mainStage.getOwner());
|
||||
|
||||
List<WorldTableItem> errorItems = new ArrayList<>();
|
||||
|
||||
AtomicBoolean haltThread = new AtomicBoolean(false);
|
||||
|
||||
Task<Boolean> task = new Task<Boolean>() {
|
||||
@Override public Boolean call() {
|
||||
|
||||
for (int w = 0; w < ((TableView<?>)content).getItems().size(); w++) {
|
||||
if (haltThread.get()) return true;
|
||||
WorldList wl = (WorldList)((TableView<?>)content).getItems().get(w);
|
||||
|
||||
String value = wl.getValue();
|
||||
int index = ((TableView<?>)content).getItems().indexOf(wl);
|
||||
|
||||
WorldTableItem tabItem;
|
||||
if (value.startsWith("http")) {
|
||||
Console.print("Trying '" + value + "'", 1, ConsoleType.INFO);
|
||||
try {
|
||||
if (!Console.testURL(value)) {
|
||||
Console.print("URL '" + value + "' failed!", 1, ConsoleType.ERROR);
|
||||
tabItem = new WorldTableItem(index, wl.getName(), value, false);
|
||||
errorItems.add(tabItem);
|
||||
} else {
|
||||
Console.print("URL '" + value + "' passed!", 1, ConsoleType.SUCCESS);
|
||||
tabItem = new WorldTableItem(index, wl.getName(), value, true);
|
||||
}
|
||||
checkTable.getItems().add(0, tabItem);
|
||||
} catch (IOException ioException) {
|
||||
Console.print("IOException encountered while checking URLs for Link Checker.", ConsoleType.ERROR);
|
||||
ioException.printStackTrace();
|
||||
Dialog.showException(ioException);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
checkTable.refresh();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
task.setOnRunning((a) -> alert.show());
|
||||
task.setOnSucceeded((a) -> {
|
||||
alert.close();
|
||||
showLinkResults(errorItems);
|
||||
});
|
||||
task.setOnFailed((a) -> {
|
||||
Console.print("Link Checking failed for unknown reasons.", ConsoleType.ERROR);
|
||||
Dialog.showException(new Exception("Unknown"));
|
||||
alert.close();
|
||||
});
|
||||
Thread taskTh = new Thread(task);
|
||||
taskTh.start();
|
||||
|
||||
alert.setOnCloseRequest((a) -> {
|
||||
Console.print("Closing Link Check", 1, ConsoleType.INFO);
|
||||
haltThread.set(true);
|
||||
alert.close();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
TableColumn<WorldList, String> indexColumn = new TableColumn<>("#");
|
||||
indexColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.05));
|
||||
indexColumn.setCellValueFactory(p -> new ReadOnlyObjectWrapper(((TableView<?>)content).getItems().indexOf(p.getValue())));
|
||||
indexColumn.setSortable(false);
|
||||
indexColumn.setEditable(false);
|
||||
|
||||
TableColumn<WorldList, String> labelColumn = new TableColumn<>("Label");
|
||||
labelColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.4));
|
||||
labelColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
|
||||
labelColumn.setCellFactory(TextFieldTableCell.forTableColumn());
|
||||
labelColumn.setSortable(false);
|
||||
|
||||
labelColumn.setOnEditCommit(t -> {
|
||||
commandStack.doCommand(new Command() {
|
||||
final String oldValue = t.getOldValue();
|
||||
final String newValue = t.getNewValue();
|
||||
WorldList item = t.getTableView().getItems().get(t.getTablePosition().getRow());
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Editing Label: '" + oldValue + "' -> '" + newValue + "'", 1, ConsoleType.DEBUG);
|
||||
t.getTableView().getItems().get(t.getTablePosition().getRow()).setName(newValue);
|
||||
((TableView<?>) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
Console.print("Undoing Label: '" + oldValue + "' <- '" + newValue + "'", 1, ConsoleType.DEBUG);
|
||||
item.setName(oldValue);
|
||||
((TableView<?>)content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TableColumn<WorldList, String> valueColumn = new TableColumn<>("Value");
|
||||
valueColumn.prefWidthProperty().bind(content.widthProperty().multiply(0.525));
|
||||
valueColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
|
||||
valueColumn.setCellFactory(TextFieldTableCell.forTableColumn());
|
||||
valueColumn.setSortable(false);
|
||||
|
||||
valueColumn.setOnEditCommit(t -> {
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
final String oldValue = t.getOldValue();
|
||||
final String newValue = t.getNewValue();
|
||||
WorldList item = t.getTableView().getItems().get(t.getTablePosition().getRow());
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Editing Value: '" + oldValue + "' -> '" + newValue + "'", 1, ConsoleType.DEBUG);
|
||||
t.getTableView().getItems().get(t.getTablePosition().getRow()).setValue(newValue);
|
||||
((TableView<?>) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
Console.print("Undoing Value: '" + oldValue + "' <- '" + newValue + "'", 1, ConsoleType.DEBUG);
|
||||
item.setValue(oldValue);
|
||||
((TableView<?>)content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
for (WorldList list : worldList.getValues()) {
|
||||
((TableView<WorldList>)content).getItems().add(list);
|
||||
}
|
||||
Console.print("List values added.", 1, ConsoleType.INFO);
|
||||
|
||||
((TableView<WorldList>)content).getColumns().addAll(indexColumn, labelColumn, valueColumn);
|
||||
|
||||
VBox.setVgrow(content, Priority.ALWAYS);
|
||||
HBox.setHgrow(toolBar, Priority.ALWAYS);
|
||||
VBox.setVgrow(toolBar, Priority.ALWAYS);
|
||||
|
||||
VBox endV = new VBox(content, findingBox);
|
||||
HBox.setHgrow(endV, Priority.ALWAYS);
|
||||
VBox.setVgrow(endV, Priority.ALWAYS);
|
||||
|
||||
switch (Main.configManager.getIntValue(ConfigEntry.toolbarPos)) {
|
||||
case 0:
|
||||
toolBar.setOrientation(Orientation.HORIZONTAL);
|
||||
return new VBox(toolBar, endV);
|
||||
case 1:
|
||||
toolBar.setOrientation(Orientation.VERTICAL);
|
||||
return new HBox(endV, toolBar);
|
||||
case 2:
|
||||
toolBar.setOrientation(Orientation.HORIZONTAL);
|
||||
return new VBox(endV, toolBar);
|
||||
default:
|
||||
case 3:
|
||||
toolBar.setOrientation(Orientation.VERTICAL);
|
||||
return new HBox(toolBar, endV);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addItem() {
|
||||
assert content instanceof TableView;
|
||||
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
WorldList newData;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Adding new item", 1, ConsoleType.DEBUG);
|
||||
newData = createItem(worldList.classType);
|
||||
worldList.add(newData);
|
||||
((TableView)content).getItems().add(newData);
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
Console.print("Undoing new item", 1, ConsoleType.DEBUG);
|
||||
worldList.remove(newData);
|
||||
((TableView)content).getItems().remove(newData);
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteItem(int i) {
|
||||
assert content instanceof TableView;
|
||||
|
||||
if (i >= 0 && ((TableView<?>)content).getItems().size() > i) {
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
WorldList item = (WorldList) ((TableView<?>) content).getItems().get(i);
|
||||
int index = i;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Deleting Item", 1, ConsoleType.DEBUG);
|
||||
worldList.remove(i);
|
||||
((TableView) content).getItems().remove(i);
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
Console.print("Undoing Delete", 1, ConsoleType.DEBUG);
|
||||
worldList.add(index, item);
|
||||
((TableView) content).getItems().add(index, item);
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
} else Console.print("Unable to delete item: No item selected!", ConsoleType.WARNING);
|
||||
}
|
||||
|
||||
public void moveValue(int i, int moveBy) {
|
||||
assert content instanceof TableView;
|
||||
|
||||
if (i >= 0 && i + moveBy >= 0 && ((TableView<?>)content).getItems().size() > i && ((TableView<?>)content).getItems().size() > i + moveBy) {
|
||||
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
final WorldList item = (WorldList) ((TableView) content).getItems().get(i);
|
||||
final WorldList rItem = (WorldList) ((TableView) content).getItems().get(i + moveBy);
|
||||
final int index = i;
|
||||
final int moved = moveBy;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Moving index " + index + " by " + moveBy, 1, ConsoleType.DEBUG);
|
||||
doMove(i, rItem);
|
||||
doMove(i + moveBy, item);
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
Console.print("Undoing move of index " + index + " by " + moveBy, 1, ConsoleType.DEBUG);
|
||||
doMove(index + moved, rItem);
|
||||
doMove(index, item);
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
private void doMove(int i, WorldList o) {
|
||||
((TableView) content).getItems().set(i, o);
|
||||
worldList.set(i, o);
|
||||
}
|
||||
});
|
||||
} else Console.print("Cannot move item.", ConsoleType.WARNING);
|
||||
}
|
||||
|
||||
public void setFocus(int i) {
|
||||
Console.print("Forced Focus on index " + i, 1, ConsoleType.DEBUG);
|
||||
((TableView)content).getSelectionModel().select(i);
|
||||
((TableView)content).scrollTo(i);
|
||||
}
|
||||
|
||||
private void quitTab() {
|
||||
if (!getSaved()) {
|
||||
Console.print("Displaying Quit alert", 1, ConsoleType.DEBUG);
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setTitle("Close Tab");
|
||||
alert.setHeaderText("Are you sure you want to close this tab?");
|
||||
alert.setContentText("You have unsaved changes. Closing now will lose your progress.");
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
ButtonType dontSaveButton = new ButtonType("Discard Changes");
|
||||
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||
|
||||
alert.getButtonTypes().setAll(dontSaveButton, buttonTypeCancel);
|
||||
|
||||
alert.getDialogPane().setMinSize(200,200);
|
||||
Optional<ButtonType> result = alert.showAndWait();
|
||||
if (result.get() == dontSaveButton) {
|
||||
closeTab();
|
||||
} else {
|
||||
alert.close();
|
||||
Main.setStatusText("Tab Alert Closed");
|
||||
}
|
||||
} else {
|
||||
closeTab();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void closeTab() {
|
||||
Main.setStatusText("Closing Tab");
|
||||
int index = tab.getTabPane().getSelectionModel().getSelectedIndex() - 1;
|
||||
Main.tabs.remove(index);
|
||||
|
||||
EventHandler<Event> handler = tab.getOnClosed();
|
||||
if (null != handler) {
|
||||
handler.handle(null);
|
||||
} else {
|
||||
tab.getTabPane().getTabs().remove(tab);
|
||||
}
|
||||
Console.print("Tab closed", 1, ConsoleType.DEBUG);
|
||||
}
|
||||
|
||||
private void setIcon(WorldsType type) {
|
||||
switch (type) {
|
||||
default:
|
||||
tab.setGraphic(new ImageView(AppIcon.unknownFile));
|
||||
break;
|
||||
case AVATAR:
|
||||
tab.setGraphic(new ImageView(AppIcon.avatarFile));
|
||||
break;
|
||||
case WORLDSMARK:
|
||||
tab.setGraphic(new ImageView(AppIcon.markFile));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Console.print("Performing tooltip and title update", 1, ConsoleType.DEBUG);
|
||||
if (file != null) tab.setTooltip(new Tooltip(file.getAbsolutePath()));
|
||||
else tab.setTooltip(new Tooltip(worldList.classType.name));
|
||||
tab.setText(generateTitle());
|
||||
setIcon(worldList.classType);
|
||||
}
|
||||
|
||||
public void update(File newFile) {
|
||||
this.file = newFile;
|
||||
update();
|
||||
}
|
||||
|
||||
private String generateTitle() {
|
||||
if (file != null) {
|
||||
return file.getName();
|
||||
} else {
|
||||
switch (worldList.classType) {
|
||||
default:
|
||||
return "Untitled";
|
||||
case AVATAR:
|
||||
return "Untitled.avatars";
|
||||
case WORLDSMARK:
|
||||
return "Untitled.worldsmarks";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setSaved(boolean value) {
|
||||
if (!value) {
|
||||
modified = true;
|
||||
tab.setGraphic(new ImageView(AppIcon.saveFile));
|
||||
} else{
|
||||
update();
|
||||
modified = false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getSaved() {
|
||||
return !modified;
|
||||
}
|
||||
|
||||
public WorldList createItem(WorldsType type) {
|
||||
switch (type) {
|
||||
default:
|
||||
return null;
|
||||
case AVATAR:
|
||||
return new AvatarObject("New Avatar", "avatar:holden.mov");
|
||||
case WORLDSMARK:
|
||||
return new MarkObject("New Mark", "home:GroundZero/groundzero.world");
|
||||
}
|
||||
}
|
||||
|
||||
public void doUndo() {
|
||||
if (commandStack.canUndo()) {
|
||||
commandStack.undo();
|
||||
Main.setStatusText("Undid last operation.");
|
||||
} else {
|
||||
Console.print("Nothing to undo.");
|
||||
Main.setStatusText("Nothing to undo.");
|
||||
}
|
||||
}
|
||||
|
||||
public void doRedo() {
|
||||
if (commandStack.canRedo()) {
|
||||
commandStack.redo();
|
||||
Main.setStatusText("Redid last operation.");
|
||||
} else {
|
||||
Console.print("Nothing to redo.");
|
||||
Main.setStatusText("Nothing to redo.");
|
||||
}
|
||||
}
|
||||
|
||||
public void showLinkResults(List<WorldTableItem> list) {
|
||||
Console.print("Displaying Link Checker results", 1, ConsoleType.INFO);
|
||||
AtomicInteger addition = new AtomicInteger();
|
||||
addition.set(0);
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.getDialogPane().setMinWidth(800);
|
||||
alert.setResizable(true);
|
||||
alert.setTitle("Link Checker Results");
|
||||
alert.setHeaderText("The followings links have been found to be dead: " + list.size() + " out of " + worldList.size());
|
||||
alert.initOwner(Main.mainStage);
|
||||
|
||||
Button deleteBtn = new Button();
|
||||
deleteBtn.setTooltip(new Tooltip("Delete"));
|
||||
deleteBtn.setGraphic(new ImageView(AppIcon.remove));
|
||||
Button deleteAllBtn = new Button("Delete All");
|
||||
deleteAllBtn.setTooltip(new Tooltip("Delete All"));
|
||||
deleteAllBtn.setGraphic(new ImageView(AppIcon.removeAll));
|
||||
|
||||
TableView<WorldTableItem> errorTable = new TableView<>();
|
||||
errorTable.setEditable(true);
|
||||
|
||||
errorTable.setMaxWidth(Double.MAX_VALUE);
|
||||
errorTable.setMaxHeight(Double.MAX_VALUE);
|
||||
GridPane.setVgrow(errorTable, Priority.ALWAYS);
|
||||
GridPane.setHgrow(errorTable, Priority.ALWAYS);
|
||||
|
||||
TableColumn<WorldTableItem, Integer> indexColumn = new TableColumn<>("#");
|
||||
indexColumn.prefWidthProperty().bind(errorTable.widthProperty().multiply(0.05));
|
||||
indexColumn.setCellValueFactory(new PropertyValueFactory<>("index"));
|
||||
indexColumn.setEditable(false);
|
||||
|
||||
TableColumn<WorldTableItem, String> labelColumn = new TableColumn<>("Label");
|
||||
labelColumn.prefWidthProperty().bind(errorTable.widthProperty().multiply(0.4));
|
||||
labelColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
|
||||
labelColumn.setCellFactory(TextFieldTableCell.<WorldTableItem>forTableColumn());
|
||||
labelColumn.setEditable(true);
|
||||
labelColumn.setOnEditCommit(t -> {
|
||||
commandStack.doCommand(
|
||||
new Command() {
|
||||
|
||||
String oldValue = t.getOldValue();
|
||||
String newValue = t.getNewValue();
|
||||
WorldList item = t.getTableView().getItems().get(t.getTablePosition().getRow());
|
||||
WorldList tableItem = ((WorldList) ((TableView) content).getItems().get(t.getRowValue().getIndex() + addition.get()));
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
item.setName(newValue);
|
||||
tableItem.setName(newValue);
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
item.setName(oldValue);
|
||||
tableItem.setName(oldValue);
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TableColumn<WorldTableItem, String> valueColumn = new TableColumn<>("Value");
|
||||
valueColumn.prefWidthProperty().bind(errorTable.widthProperty().multiply(0.525));
|
||||
valueColumn.setCellValueFactory(new PropertyValueFactory<>("value"));
|
||||
valueColumn.setCellFactory(TextFieldTableCell.<WorldTableItem>forTableColumn());
|
||||
valueColumn.setEditable(true);
|
||||
valueColumn.setOnEditCommit(t -> {
|
||||
commandStack.doCommand(
|
||||
new Command() {
|
||||
|
||||
String oldValue = t.getOldValue();
|
||||
String newValue = t.getNewValue();
|
||||
WorldList item = t.getTableView().getItems().get(t.getTablePosition().getRow());
|
||||
WorldList tableItem = ((WorldList) ((TableView) content).getItems().get(t.getRowValue().getIndex() + addition.get()));
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
item.setValue(newValue);
|
||||
tableItem.setValue(newValue);
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
item.setValue(oldValue);
|
||||
tableItem.setValue(oldValue);
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
for (WorldTableItem item : list) {
|
||||
errorTable.getItems().add(item);
|
||||
}
|
||||
|
||||
|
||||
ToolBar btnBar = new ToolBar();
|
||||
btnBar.getItems().addAll(deleteBtn, deleteAllBtn);
|
||||
|
||||
errorTable.getColumns().addAll(indexColumn, labelColumn, valueColumn);
|
||||
|
||||
VBox vBox = new VBox(errorTable, btnBar);
|
||||
|
||||
alert.getDialogPane().setContent(vBox);
|
||||
|
||||
deleteBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> { commandStack.doCommand(
|
||||
new Command() {
|
||||
|
||||
int selected = errorTable.getSelectionModel().getSelectedIndex();
|
||||
int tableSel = errorTable.getItems().get(selected).getIndex();
|
||||
WorldTableItem item = errorTable.getItems().get(selected);
|
||||
int added = tableSel + addition.get();
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
worldList.remove(tableSel + addition.get());
|
||||
((TableView)content).getItems().remove(tableSel + addition.get());
|
||||
|
||||
errorTable.getItems().remove(selected);
|
||||
list.remove(selected);
|
||||
addition.getAndDecrement();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
worldList.add(added, item);
|
||||
((TableView)content).getItems().add(added, item);
|
||||
|
||||
errorTable.getItems().add(selected, item);
|
||||
list.add(selected, item);
|
||||
addition.getAndIncrement();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
deleteAllBtn.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
Alert askSure = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
askSure.setTitle("Delete All?");
|
||||
askSure.setHeaderText("Are you sure you want to delete all the items in this list?");
|
||||
askSure.setContentText("You won't be able to undo this change!");
|
||||
|
||||
ButtonType delSureButton = new ButtonType("Discard Changes");
|
||||
ButtonType buttonTypeCancel = new ButtonType("Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
|
||||
|
||||
askSure.getButtonTypes().setAll(delSureButton, buttonTypeCancel);
|
||||
|
||||
askSure.getDialogPane().setMinSize(200,200);
|
||||
Optional<ButtonType> result = askSure.showAndWait();
|
||||
if (result.get() == delSureButton) {
|
||||
for (WorldTableItem item : list) {
|
||||
errorTable.getItems().remove(0);
|
||||
worldList.remove(item.getIndex() + addition.get());
|
||||
((TableView) content).getItems().remove(item.getIndex() + addition.get());
|
||||
addition.getAndDecrement();
|
||||
}
|
||||
setSaved(false);
|
||||
} else {
|
||||
askSure.close();
|
||||
}
|
||||
});
|
||||
|
||||
alert.showAndWait();
|
||||
}
|
||||
|
||||
private VBox getFindPane() {
|
||||
Console.print("Initializing FindPane", 1, ConsoleType.INFO);
|
||||
Text findText = new Text("Find Text");
|
||||
findText.setFont(Font.font("Verdana", FontWeight.NORMAL, FontPosture.REGULAR, 12));
|
||||
TextField findInput = new TextField();
|
||||
|
||||
Text replText = new Text("Replace Text");
|
||||
replText.setFont(Font.font("Verdana", FontWeight.NORMAL, FontPosture.REGULAR, 12));
|
||||
TextField replInput = new TextField();
|
||||
|
||||
Slider selSlider = new Slider(-1,1,0);
|
||||
selSlider.setMajorTickUnit(1);
|
||||
selSlider.setMinorTickCount(0);
|
||||
selSlider.setSnapToTicks(true);
|
||||
Text labelTxt = new Text("Label");
|
||||
Text valueTxt = new Text("Value");
|
||||
|
||||
HBox.setHgrow(selSlider, Priority.ALWAYS);
|
||||
HBox.setHgrow(labelTxt, Priority.ALWAYS);
|
||||
HBox.setHgrow(valueTxt, Priority.ALWAYS);
|
||||
|
||||
GridPane findBar = new GridPane();
|
||||
|
||||
Button findButton = new Button("Find");
|
||||
findButton.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
Console.print("Performing find", 1, ConsoleType.INFO);
|
||||
int curI = ((TableView)content).getSelectionModel().getSelectedIndex();
|
||||
if (curI < 0) curI = 0;
|
||||
Main.setStatusText("Searching...");
|
||||
for (int a = curI+1; a < worldList.size(); a++) {
|
||||
if (worldList.get(a).getName().contains(findInput.getCharacters()) || worldList.get(a).getValue().contains(findInput.getCharacters())) {
|
||||
setFocus(a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Button replButton = new Button("Replace");
|
||||
replButton.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
WorldList replaced;
|
||||
final int index = ((TableView<WorldList>)content).getSelectionModel().getSelectedIndex();
|
||||
final double slider = selSlider.getValue();
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Performing replace", 1, ConsoleType.INFO);
|
||||
WorldList item = ((TableView<WorldList>)content).getSelectionModel().getSelectedItem();
|
||||
if (item.getName().contains(findInput.getCharacters()) || item.getValue().contains(findInput.getCharacters())) {
|
||||
WorldTableItem tableItem = new WorldTableItem(((TableView) content).getItems().indexOf(item), item.getName(), item.getValue());
|
||||
if (selSlider.getValue() >= 0)
|
||||
item.setValue(item.getValue().replace(findInput.getCharacters(), replInput.getCharacters()));
|
||||
if (selSlider.getValue() <= 0)
|
||||
item.setName(item.getName().replace(findInput.getCharacters(), replInput.getCharacters()));
|
||||
Main.setStatusText("Replaced item");
|
||||
replaced = tableItem;
|
||||
}
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
WorldList item = (WorldList)((TableView) content).getItems().get(index);
|
||||
if (slider >= 0) item.setValue(replaced.getValue());
|
||||
if (slider <= 0) item.setName(replaced.getName());
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Button replAllButton = new Button("Replace All");
|
||||
replAllButton.addEventFilter(MouseEvent.MOUSE_CLICKED, e -> {
|
||||
commandStack.doCommand(new Command() {
|
||||
|
||||
final List<WorldTableItem> replaced = new ArrayList<>();
|
||||
final double slider = selSlider.getValue();
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Console.print("Performing replace all", 1, ConsoleType.INFO);
|
||||
int count = 0;
|
||||
for (WorldList item : worldList.getValues()) {
|
||||
if (item.getName().contains(findInput.getCharacters()) || item.getValue().contains(findInput.getCharacters())) {
|
||||
count++;
|
||||
WorldTableItem tableItem = new WorldTableItem(((TableView)content).getItems().indexOf(item), item.getName(), item.getValue());
|
||||
if (selSlider.getValue() >= 0) item.setValue(item.getValue().replace(findInput.getCharacters(), replInput.getCharacters()));
|
||||
if (selSlider.getValue() <= 0) item.setName(item.getName().replace(findInput.getCharacters(), replInput.getCharacters()));
|
||||
replaced.add(tableItem);
|
||||
}
|
||||
}
|
||||
Main.setStatusText("Replaced " + count + " items.");
|
||||
((TableView)content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void undo() {
|
||||
for (WorldTableItem tableItem : replaced) {
|
||||
WorldList item = (WorldList)((TableView)content).getItems().get(tableItem.getIndex());
|
||||
if (slider >= 0) item.setValue(tableItem.getValue());
|
||||
if (slider <= 0) item.setName(tableItem.getName());
|
||||
}
|
||||
((TableView) content).refresh();
|
||||
setSaved(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
ButtonBar btns = new ButtonBar();
|
||||
btns.getButtons().addAll(findButton, replButton, replAllButton);
|
||||
GridPane.setColumnSpan(btns, 2);
|
||||
|
||||
findBar.add(findText, 0, 0);
|
||||
findBar.add(findInput, 1, 0);
|
||||
|
||||
findBar.add(replText, 0, 1);
|
||||
findBar.add(replInput, 1, 1);
|
||||
|
||||
findBar.add(new HBox(labelTxt, selSlider, valueTxt), 0, 2);
|
||||
findBar.add(btns, 1, 2);
|
||||
|
||||
GridPane.setHgrow(findInput, Priority.ALWAYS);
|
||||
GridPane.setHgrow(replInput, Priority.ALWAYS);
|
||||
GridPane.setHgrow(btns, Priority.ALWAYS);
|
||||
findBar.setHgap(5);
|
||||
findBar.setVgap(5);
|
||||
|
||||
findBar.setPadding(new Insets(10, 10, 10, 10));
|
||||
VBox.setVgrow(findBar, Priority.ALWAYS);
|
||||
|
||||
Console.print("Completed FindPane", 1, ConsoleType.INFO);
|
||||
return new VBox(findBar);
|
||||
}
|
||||
}
|
||||
8
src/main/resources/dark.css
Normal file
@@ -0,0 +1,8 @@
|
||||
.root {
|
||||
-fx-base: rgba(25, 25, 25, 255);
|
||||
}
|
||||
|
||||
.table-view {
|
||||
-fx-base: rgba(25,25,25,255);
|
||||
text-color: rgba(200,200,200,255);
|
||||
}
|
||||
BIN
src/main/resources/icons/avatar.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
src/main/resources/icons/conf.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
src/main/resources/icons/delete-all.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/main/resources/icons/delete.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/main/resources/icons/down.png
Normal file
|
After Width: | Height: | Size: 896 B |
BIN
src/main/resources/icons/file-plus.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
src/main/resources/icons/file.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
src/main/resources/icons/find.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
src/main/resources/icons/folder.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/main/resources/icons/link.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
src/main/resources/icons/mark.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
src/main/resources/icons/plus.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
src/main/resources/icons/quit.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/main/resources/icons/redo.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/icons/save-as.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/main/resources/icons/save.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/icons/undo.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/main/resources/icons/up.png
Normal file
|
After Width: | Height: | Size: 878 B |
BIN
src/main/resources/logo.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
3
src/main/resources/project.properties
Normal file
@@ -0,0 +1,3 @@
|
||||
version=${project.version}
|
||||
artifactId=${project.artifactId}
|
||||
buildDate=${buildNumber}
|
||||