Commit edda0d6f authored by Nico Eckes's avatar Nico Eckes

Next editor push

parent ba31e6b0
Pipeline #794 passed with stage
in 3 minutes and 8 seconds
......@@ -9,8 +9,9 @@ import javafx.stage.Stage;
public class Main extends Application {
public static final Image ICON = new Image(Main.class.getResourceAsStream("img/PermIO.png"));
public static final boolean DEBUG = false;
public static void main(String[] args) {
public static void main(String[] args) {
launch(args);
}
......
......@@ -27,6 +27,9 @@ import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public abstract class ExtendedList<T> extends VBox {
......@@ -36,11 +39,11 @@ public abstract class ExtendedList<T> extends VBox {
@FXML public TextField addField;
@FXML public ListView<T> list;
@FXML public HBox toolbar;
private ObservableList<T> items;
ObservableList<T> items;
public final ObjectProperty<T> selectedItem = new SimpleObjectProperty<>();
public ExtendedList() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ExtendedList.fxml"));
FXMLLoader loader = new FXMLLoader(ExtendedList.class.getResource("ExtendedList.fxml"));
loader.setController(this);
try {
loader.load();
......@@ -76,7 +79,7 @@ public abstract class ExtendedList<T> extends VBox {
String paste = (String) Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
if (paste == null) return;
for (T item: provideItem(paste.split("\n"))) {
if (item != null && !items.contains(item)) items.add(item);
if (item != null && !items.contains(item)) addItem(item);
}
} catch (UnsupportedFlavorException | IOException ignored) {
......@@ -120,14 +123,18 @@ public abstract class ExtendedList<T> extends VBox {
Platform.runLater(()->addField.setStyle("-fx-text-fill: red"));
return;
}
Platform.runLater(()->{
items.add(item);
Platform.runLater(()-> {
addItem(item);
addField.clear();
});
}).start();
}
}
void addItem(T item) {
Platform.runLater(()-> items.add(item));
}
abstract T[] provideItem(String... text);
abstract Node provideNode(T item);
......
package com.unitedworldminers.permio.editor.component;
import com.unitedworldminers.permio.editor.data.Group;
import com.unitedworldminers.permio.editor.data.Player;
import com.unitedworldminers.permio.editor.screen.MainScreen;
import com.unitedworldminers.permio.editor.util.Utils;
import javafx.collections.ListChangeListener;
import javafx.scene.Node;
import javafx.scene.control.Label;
......
package com.unitedworldminers.permio.editor.component;
import com.unitedworldminers.permio.editor.Main;
import com.unitedworldminers.permio.editor.data.Player;
import com.unitedworldminers.permio.editor.data.PlayerProfile;
import com.unitedworldminers.permio.editor.screen.GroupsScreen;
import com.unitedworldminers.permio.editor.screen.MainScreen;
import com.unitedworldminers.permio.editor.util.Utils;
import javafx.geometry.Insets;
import javafx.scene.Node;
......@@ -10,8 +13,6 @@ import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Region;
import java.util.Comparator;
public class PlayerList extends ExtendedList<Player> {
@Override
public void initialize() {
......@@ -22,7 +23,18 @@ public class PlayerList extends ExtendedList<Player> {
@Override
Player[] provideItem(String... text) {
return Utils.transform(PlayerProfile.query(text), profile -> profile == null ? null : new Player(profile), Player[]::new);
return Utils.transform(PlayerProfile.query(text), profile -> {
if (profile == null) return null; else {
Player p = new Player(profile);
p.group.set(GroupsScreen.activeGroup.get());
return p;
}
}, Player[]::new);
}
@Override
void addItem(Player item) {
MainScreen.players.add(item);
}
@Override
......
package com.unitedworldminers.permio.editor.data;
import com.unitedworldminers.permio.editor.exception.LoadException;
import com.unitedworldminers.permio.editor.screen.MainScreen;
import com.unitedworldminers.permio.editor.util.Utils;
import com.unitedworldminers.permio.editor.util.YamlUtil;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
......@@ -8,8 +10,10 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import org.apache.commons.vfs2.FileContent;
import javafx.scene.control.Alert;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.VFS;
import org.jetbrains.annotations.NotNull;
import java.util.*;
......@@ -20,24 +24,34 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
public class GroupData implements ObservableList<Group> {
public FileContent file;
private ObservableList<Group> groups;
public FileObject file;
private final ObservableList<Group> groups;
public GroupData() {
groups = FXCollections.observableArrayList();
addListener((ListChangeListener<Group>) c -> {
c.next();
for (Player p: MainScreen.players) {
if (c.getRemoved().contains(p.group.get())) p.group.set(null);
}
for (Group g: MainScreen.groups) {
if (c.getRemoved().contains(g.inherits.get())) g.inherits.set(null);
}
});
}
public GroupData(FileContent file) throws LoadException {
public GroupData(FileObject file) throws LoadException {
this();
this.file = file;
groups = FXCollections.observableArrayList();
Map<String, Map<String, Object>> rawGroups;
try {
rawGroups = YamlUtil.loadYaml(file);
rawGroups = YamlUtil.loadYaml(file.getContent());
} catch (FileSystemException e) {
throw new LoadException("Could not load groups from " + file.getFile().getPublicURIString(), e);
throw new LoadException("Could not load groups from " + file.getPublicURIString(), e);
}
if (rawGroups == null) throw new LoadException("Could not load groups from " + file.getFile().getPublicURIString());
if (rawGroups == null) throw new LoadException("Could not load groups from " + file.getPublicURIString());
rawGroups.keySet().forEach(gid -> provideGroup(gid, rawGroups));
}
......@@ -57,10 +71,17 @@ public class GroupData implements ObservableList<Group> {
}
public void save() {
if (file == null) {
try {
file = VFS.getManager().resolveFile(Objects.requireNonNull(Utils.fileChooser(Utils.ChooseType.SAVE, null, "Save groups", "groups.yml")).toUri());
} catch (FileSystemException | NullPointerException e) {
return;
}
}
try {
YamlUtil.saveYaml(groups.stream().collect(Collectors.toMap(g->g.name, Group::save)), file);
YamlUtil.saveYaml(groups.stream().collect(Collectors.toMap(g->g.name, Group::save)), file.getContent());
} catch (FileSystemException e) {
e.printStackTrace();
new Alert(Alert.AlertType.ERROR, "Could not save group data: " + e.getMessage()).showAndWait();
}
}
......
package com.unitedworldminers.permio.editor.data;
import com.unitedworldminers.permio.editor.exception.LoadException;
import com.unitedworldminers.permio.editor.util.Utils;
import com.unitedworldminers.permio.editor.util.YamlUtil;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
......@@ -8,8 +9,10 @@ import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import org.apache.commons.vfs2.FileContent;
import javafx.scene.control.Alert;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.VFS;
import org.jetbrains.annotations.NotNull;
import java.util.*;
......@@ -20,22 +23,22 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
public class PlayerData implements ObservableList<Player> {
public FileContent file;
public ObservableList<Player> players;
public FileObject file;
public final ObservableList<Player> players;
public PlayerData() {
players = FXCollections.observableArrayList();
}
public PlayerData(FileContent file, GroupData groupData) throws LoadException {
public PlayerData(FileObject file, GroupData groupData) throws LoadException {
this.file = file;
Map<String, Map<String, Object>> rawPlayers;
try {
rawPlayers = YamlUtil.loadYaml(file);
rawPlayers = YamlUtil.loadYaml(file.getContent());
} catch (FileSystemException e) {
throw new LoadException("Could not load players from " + file.getFile().getPublicURIString());
throw new LoadException("Could not load players from " + file.getPublicURIString());
}
if (rawPlayers == null) throw new LoadException("Could not load players from " + file.getFile().getPublicURIString());
if (rawPlayers == null) throw new LoadException("Could not load players from " + file.getPublicURIString());
players = FXCollections.observableArrayList(rawPlayers.entrySet().stream().map(e->new Player(PlayerProfile.query(e.getKey())[0], e.getValue(), groupData)).collect(Collectors.toList()));
}
......@@ -45,10 +48,17 @@ public class PlayerData implements ObservableList<Player> {
}
public void save() {
if (file == null) {
try {
file = VFS.getManager().resolveFile(Objects.requireNonNull(Utils.fileChooser(Utils.ChooseType.SAVE, null, "Save players", "players.yml")).toUri());
} catch (FileSystemException | NullPointerException e) {
return;
}
}
try {
YamlUtil.saveYaml(players.stream().collect(Collectors.toMap(p->p.identity.uuid.toString(), Player::save)), file);
YamlUtil.saveYaml(players.stream().collect(Collectors.toMap(p->p.identity.uuid.toString(), Player::save)), file.getContent());
} catch (FileSystemException e) {
e.printStackTrace();
new Alert(Alert.AlertType.ERROR, "Could not save player data: " + e.getMessage()).showAndWait();
}
}
......
package com.unitedworldminers.permio.editor.data;
import com.unitedworldminers.permio.editor.Main;
import com.unitedworldminers.permio.editor.util.Utils;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.image.Image;
......@@ -91,6 +93,9 @@ public class PlayerProfile {
}
public static PlayerProfile[] of(String... names) {
if (Main.DEBUG) {
return Utils.transform(names, n-> n == null ? null : cache.getOrDefault(n.toLowerCase(), new PlayerProfile(UUID.randomUUID(), n)), PlayerProfile[]::new);
}
PlayerProfile[] result = new PlayerProfile[names.length];
for (int i = 0; i < names.length; i += 100) {
for (int j = 0; j < 100 && i + j < names.length; j++) result[i + j] = names[i + j] == null ? null : cache.get(names[i + j].toLowerCase());
......
......@@ -4,6 +4,11 @@ import com.unitedworldminers.permio.editor.data.Group;
import com.unitedworldminers.permio.editor.component.GroupsList;
import com.unitedworldminers.permio.editor.component.PermissionList;
import com.unitedworldminers.permio.editor.component.PlayerList;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.fxml.FXML;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
......@@ -18,14 +23,18 @@ public class GroupsScreen {
@FXML private PermissionList permissions;
@FXML private PlayerList players;
@FXML private VBox groupMeta;
public static final ObjectProperty<Group> activeGroup = new SimpleObjectProperty<>();
@FXML
private void initialize() {
// groupmeta width (combobox, spinner) enforcement
inheritance.prefWidthProperty().bind(((Region) inheritance.getParent()).widthProperty());
// LISTENERS
groupsList.list.getSelectionModel().selectedItemProperty().addListener((obs, old, now) -> selectGroup(old, now));
activeGroup.bind(groupsList.list.getSelectionModel().selectedItemProperty());
activeGroup.addListener((observable, oldValue, newValue) -> {
selectGroup(oldValue, newValue);
groupsList.list.getSelectionModel().select(newValue);
});
}
public void load() {
......@@ -40,6 +49,7 @@ public class GroupsScreen {
setElementsDisabled(now == null);
if (now != null) {
permissions.setSource(now.permissions);
players.setSource(MainScreen.players.filtered(p-> now.equals(p.group.get())));
if (old != null) inheritance.valueProperty().unbindBidirectional(old.inherits);
inheritance.setItems(MainScreen.groups.filtered(g -> !g.isChildOf(now)));
......@@ -50,6 +60,9 @@ public class GroupsScreen {
if (old != null) suffix.textProperty().unbindBidirectional(old.suffix);
suffix.textProperty().bindBidirectional(now.suffix);
} else {
permissions.setSource(FXCollections.observableArrayList());
players.setSource(FXCollections.observableArrayList());
}
}
......
package com.unitedworldminers.permio.editor.screen;
import com.sun.javafx.scene.control.skin.MenuBarSkin;
import com.unitedworldminers.permio.editor.Main;
import com.unitedworldminers.permio.editor.data.GroupData;
import com.unitedworldminers.permio.editor.data.Player;
import com.unitedworldminers.permio.editor.data.PlayerData;
import com.unitedworldminers.permio.editor.exception.LoadException;
import javafx.event.ActionEvent;
import com.unitedworldminers.permio.editor.util.Utils;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.MenuBar;
import javafx.stage.FileChooser;
import javafx.scene.control.*;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.Window;
import javafx.util.Pair;
import org.apache.commons.vfs2.FileContent;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemManager;
import org.apache.commons.vfs2.VFS;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
public class MainScreen {
@FXML private Node groupsScreen;
@FXML private TabPane tabPane;
@FXML private GroupsScreen groupsScreenController;
@FXML private PlayersScreen playersScreenController;
@FXML private MenuBar menuBar;
public static GroupData groups = new GroupData();
......@@ -36,26 +38,24 @@ public class MainScreen {
@FXML
private void initialize() {
menuBar.getMenus().add(new InstantMenu("Open", this::menuOpen));
menuBar.getMenus().add(new InstantMenu("Open SFTP", this::menuOpenSFTP));
menuBar.getMenus().add(new InstantMenu("Save", this::menuSave));
menuBar.getMenus().add(new InstantMenu("Reload", this::menuReload));
// load if in fitting dir
boolean loaded = load(Paths.get("groups.yml"), Paths.get("players.yml")) != null || load(Paths.get("../groups.yml"), Paths.get("../players.yml")) != null;
boolean loaded = load(Paths.get("groups.yml"), Paths.get("players.yml")) == null || load(Paths.get("../groups.yml"), Paths.get("../players.yml")) == null;
if (!loaded) load();
System.out.println(loaded ? "loaded" : "empty");
}
@FXML
private void menuOpen(ActionEvent actionEvent) {
private void menuOpen() {
Window window = menuBar.getScene().getWindow();
FileChooser chooser = new FileChooser();
chooser.setSelectedExtensionFilter(new FileChooser.ExtensionFilter("YAML file", "*.yml"));
chooser.setInitialDirectory(new File("."));
chooser.setTitle("Select groups file");
chooser.setInitialFileName("groups.yml");
Path groups = Optional.ofNullable(chooser.showOpenDialog(window)).map(File::toPath).orElse(null);
Path groups = Utils.fileChooser(Utils.ChooseType.OPEN, window, "Select groups file", "groups.yml");
if (groups == null) return;
chooser.setTitle("Select players file");
chooser.setInitialFileName("players.yml");
Path players = Optional.ofNullable(chooser.showOpenDialog(window)).map(File::toPath).orElse(null);
Path players = Utils.fileChooser(Utils.ChooseType.OPEN, window, "Select players file", "players.yml");
if (players == null) return;
String err = load(groups, players);
......@@ -67,12 +67,12 @@ public class MainScreen {
}
@FXML
private void menuSave(ActionEvent actionEvent) {
private void menuSave() {
save();
}
@FXML
private void menuReload(ActionEvent actionEvent) {
private void menuReload() {
load(groups.file, players.file);
}
......@@ -80,14 +80,14 @@ public class MainScreen {
private String load(Path groupsFile, Path playersFile) {
try {
FileSystemManager fs = VFS.getManager();
return load(fs.resolveFile(groupsFile.toUri()).getContent(), fs.resolveFile(playersFile.toUri()).getContent());
return load(fs.resolveFile(groupsFile.toUri()), fs.resolveFile(playersFile.toUri()));
} catch (IOException e) {
return e.getMessage();
}
}
@Nullable
private String load(FileContent groups, FileContent players) {
private String load(FileObject groups, FileObject players) {
try {
MainScreen.groups = new GroupData(groups);
MainScreen.players = new PlayerData(players, MainScreen.groups);
......@@ -95,8 +95,13 @@ public class MainScreen {
return e.getMessage();
}
((GroupsScreen) groupsScreen.getUserData()).load();
load();
return null;
}
private String load() {
groupsScreenController.load();
return null;
}
......@@ -125,7 +130,29 @@ public class MainScreen {
}
window.showAndWait();
@SuppressWarnings("unchecked")
Pair<FileContent, FileContent> files = (Pair<FileContent, FileContent>) window.getUserData();
Pair<FileObject, FileObject> files = (Pair<FileObject, FileObject>) window.getUserData();
load(files.getKey(), files.getValue());
}
class InstantMenu extends Menu {
private final Runnable action;
public InstantMenu(String text, Runnable action) {
super(text);
this.action = action;
getItems().add(new MenuItem());
}
@Override
public void show() {
try {
Method m = MenuBarSkin.class.getDeclaredMethod("unSelectMenus");
m.setAccessible(true);
m.invoke(menuBar.getSkin());
} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
}
action.run();
}
}
}
package com.unitedworldminers.permio.editor.screen;
public class PlayersScreen {
}
package com.unitedworldminers.permio.editor.util;
import javafx.stage.FileChooser;
import javafx.stage.Window;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
......@@ -29,4 +33,25 @@ public class Utils {
if (list == null) return null;
return list.stream().map(transformer).collect(Collectors.toList());
}
@Nullable
public static Path fileChooser(ChooseType type, Window parent, String title, String initialFileName) {
FileChooser chooser = new FileChooser();
chooser.setSelectedExtensionFilter(new FileChooser.ExtensionFilter("YAML file", "*.yml"));
chooser.setInitialDirectory(new File("."));
chooser.setTitle(title);
chooser.setInitialFileName(initialFileName);
File result = null;
switch (type) {
case OPEN: result = chooser.showOpenDialog(parent); break;
case SAVE: result = chooser.showSaveDialog(parent); break;
}
return result == null ? null : result.toPath();
}
public enum ChooseType {
OPEN, SAVE
}
}
......@@ -10,10 +10,7 @@
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.layout.HBox?>
<SplitPane dividerPositions="0.3, 0.7" prefHeight="482.0" prefWidth="776.0" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.unitedworldminers.permio.editor.screen.GroupsScreen">
<userData>
<fx:reference source="controller" />
</userData>
<SplitPane dividerPositions="0.3, 0.7" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.unitedworldminers.permio.editor.screen.GroupsScreen">
<VBox>
<GroupsList fx:id="groupsList" VBox.vgrow="ALWAYS">
<VBox.margin>
......
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.unitedworldminers.permio.editor.screen.MainScreen">
<MenuBar fx:id="menuBar">
<Menu mnemonicParsing="false" onAction="#menuOpen" text="Load" />
<Menu mnemonicParsing="false" onAction="#menuOpenSFTP" text="Load SFTP" />
<Menu mnemonicParsing="false" onAction="#menuSave" text="Save" />
<Menu mnemonicParsing="false" onAction="#menuReload" text="Reload" />
</MenuBar>
<TabPane prefHeight="200.0" prefWidth="200.0" side="LEFT" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="SOMETIMES">
<MenuBar fx:id="menuBar" />
<TabPane fx:id="tabPane" prefHeight="200.0" prefWidth="200.0" side="LEFT" tabClosingPolicy="UNAVAILABLE" VBox.vgrow="SOMETIMES">
<Tab closable="false" text="Groups">
<fx:include VBox.vgrow="ALWAYS" fx:id="groupsScreen" source="GroupsScreen.fxml"/>
<fx:include fx:id="groupsScreen" source="GroupsScreen.fxml" VBox.vgrow="ALWAYS" />
</Tab>
<Tab closable="false" text="Players">
<fx:include fx:id="playersScreen" source="PlayersScreen.fxml" VBox.vgrow="ALWAYS" />
</Tab>
<Tab closable="false" text="Players" />
</TabPane>
</VBox>
<?xml version="1.0" encoding="UTF-8"?>
<?import com.unitedworldminers.permio.editor.component.PermissionList?>
<?import javafx.scene.control.SplitPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>
<?import com.unitedworldminers.permio.editor.component.PlayerList?>
<SplitPane dividerPositions="0.3, 0.7" VBox.vgrow="ALWAYS" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.unitedworldminers.permio.editor.screen.PlayersScreen">
<PlayerList fx:id="players" />
<PermissionList fx:id="permissions" disable="true" />
<Pane />
</SplitPane>
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment