Commit 88cc01e5 authored by Nico Eckes's avatar Nico Eckes

follow update, next up: removing priority [ci-skip]

parent e356223f
Pipeline #751 skipped
package com.unitedworldminers.permio.editor;
import javafx.application.Platform;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
......@@ -32,7 +34,8 @@ public abstract class ExtendedList<T> extends VBox {
@FXML public TextField searchField;
@FXML public TextField addField;
@FXML public ListView<T> list;
public final ObservableList<T> items = FXCollections.observableArrayList();
private ObservableList<T> items;
public final ObjectProperty<T> selectedItem = new SimpleObjectProperty<>();
public ExtendedList() {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ExtendedList.fxml"));
......@@ -46,17 +49,13 @@ public abstract class ExtendedList<T> extends VBox {
@FXML
public void initialize() {
FilteredList<T> filteredItems = new FilteredList<>(items, t-> true);
list.setItems(filteredItems.sorted(comparator()));
searchField.textProperty().addListener(obs -> {
String filter = searchField.getText();
filteredItems.setPredicate(filter.isEmpty() ? s -> true : s -> s.toString().toLowerCase().contains(filter.toLowerCase()));
});
setSource(FXCollections.observableArrayList());
list.setCellFactory(param -> new RemoveableEntry());
list.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
list.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) ->{
if (newValue != null) selectedItem.set(newValue);
});
setOnKeyPressed(event -> {
if (event.getCode() == KeyCode.DELETE) {
for (T sel : new ArrayList<>(list.getSelectionModel().getSelectedItems())) {
......@@ -89,6 +88,17 @@ public abstract class ExtendedList<T> extends VBox {
getChildren().addAll(title, searchField, list, addField);
}
public void setSource(ObservableList<T> source) {
items = source;
FilteredList<T> filteredItems = new FilteredList<>(items, t-> true);
list.setItems(filteredItems.sorted(comparator()));
searchField.textProperty().addListener(obs -> {
String filter = searchField.getText();
filteredItems.setPredicate(filter.isEmpty() ? s -> true : s -> s.toString().toLowerCase().contains(filter.toLowerCase()));
});
}
public void reset() {
searchField.clear();
items.clear();
......@@ -130,6 +140,7 @@ public abstract class ExtendedList<T> extends VBox {
setGraphic(null);
return;
}
if (item == selectedItem.get()) list.getSelectionModel().select(item);
setMinWidth(0);
setPrefWidth(1);
......
package com.unitedworldminers.permio.editor;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public class Group {
private static final String KEY_PREFIX = "prefix";
private static final String KEY_SUFFIX = "suffix";
private static final String KEY_PERMISSIONS = "permissions";
private static final String KEY_INHERITS = "inherits";
public final String name;
public final StringProperty prefix = new SimpleStringProperty();
public final StringProperty suffix = new SimpleStringProperty();
public final ObservableList<String> permissions = FXCollections.observableArrayList();
public final ObjectProperty<Group> inherits = new SimpleObjectProperty<>();
@SuppressWarnings("unchecked")
public Group(String name, Map<String, Object> raw, Function<String, Group> inheritanceSupplier) {
this(name);
Object o = raw.get(KEY_PERMISSIONS);
if (o instanceof List) permissions.addAll((List<String>) o);
o = raw.get(KEY_INHERITS);
if (o instanceof String) inherits.set(inheritanceSupplier.apply((String) o));
o = raw.get(KEY_PREFIX);
if (o instanceof String) prefix.set((String) o);
o = raw.get(KEY_SUFFIX);
if (o instanceof String) suffix.set((String) o);
}
public Group(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
public boolean isChildOf(Group parent) {
return this == parent || (inherits.get() != null && inherits.get().isChildOf(parent));
}
}
package com.unitedworldminers.permio.editor;
import javafx.beans.InvalidationListener;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.collections.transformation.SortedList;
import org.jetbrains.annotations.NotNull;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class GroupData implements ObservableList<Group> {
public Path location = null;
private ObservableList<Group> groups;
public GroupData() {
groups = FXCollections.observableArrayList();
}
public GroupData(Path groupsFile) throws InstantiationException {
location = groupsFile;
groups = FXCollections.observableArrayList();
Map<String, Map<String, Object>> rawGroups = YamlUtil.loadYaml(groupsFile);
if (rawGroups == null) throw new InstantiationException("Could not load groups from "+groupsFile.toString());
rawGroups.keySet().forEach(gid -> provideGroup(gid, rawGroups));
}
public Group provideGroup(String gid, Map<String, Map<String, Object>> rawGroups) {
Group result = byName(gid);
if (result == null) {
result = new Group(gid, rawGroups.get(gid), s -> provideGroup(s, rawGroups));
groups.add(result);
}
return result;
}
public Group byName(String name) {
for (Group g: this) if (g.name.equals(name)) return g;
return null;
}
// delegated methods
public void addListener(ListChangeListener<? super Group> listener) {
groups.addListener(listener);
}
public void removeListener(ListChangeListener<? super Group> listener) {
groups.removeListener(listener);
}
public boolean addAll(Group... elements) {
return groups.addAll(elements);
}
public boolean setAll(Group... elements) {
return groups.setAll(elements);
}
public boolean setAll(Collection<? extends Group> col) {
return groups.setAll(col);
}
public boolean removeAll(Group... elements) {
return groups.removeAll(elements);
}
public boolean retainAll(Group... elements) {
return groups.retainAll(elements);
}
public void remove(int from, int to) {
groups.remove(from, to);
}
public FilteredList<Group> filtered(Predicate<Group> predicate) {
return groups.filtered(predicate);
}
public SortedList<Group> sorted(Comparator<Group> comparator) {
return groups.sorted(comparator);
}
public SortedList<Group> sorted() {
return groups.sorted();
}
public int size() {
return groups.size();
}
public boolean isEmpty() {
return groups.isEmpty();
}
public boolean contains(Object o) {
return groups.contains(o);
}
@NotNull
public Iterator<Group> iterator() {
return groups.iterator();
}
@NotNull
public Object[] toArray() {
return groups.toArray();
}
@SuppressWarnings("SuspiciousToArrayCall")
@NotNull
public <T> T[] toArray(@NotNull T[] a) {
return groups.toArray(a);
}
public boolean add(Group group) {
return groups.add(group);
}
public boolean remove(Object o) {
return groups.remove(o);
}
public boolean containsAll(@NotNull Collection<?> c) {
return groups.containsAll(c);
}
public boolean addAll(@NotNull Collection<? extends Group> c) {
return groups.addAll(c);
}
public boolean addAll(int index, @NotNull Collection<? extends Group> c) {
return groups.addAll(index, c);
}
public boolean removeAll(@NotNull Collection<?> c) {
return groups.removeAll(c);
}
public boolean retainAll(@NotNull Collection<?> c) {
return groups.retainAll(c);
}
public void replaceAll(UnaryOperator<Group> operator) {
groups.replaceAll(operator);
}
public void sort(Comparator<? super Group> c) {
groups.sort(c);
}
public void clear() {
groups.clear();
}
public Group get(int index) {
return groups.get(index);
}
public Group set(int index, Group element) {
return groups.set(index, element);
}
public void add(int index, Group element) {
groups.add(index, element);
}
public Group remove(int index) {
return groups.remove(index);
}
public int indexOf(Object o) {
return groups.indexOf(o);
}
public int lastIndexOf(Object o) {
return groups.lastIndexOf(o);
}
@NotNull
public ListIterator<Group> listIterator() {
return groups.listIterator();
}
@NotNull
public ListIterator<Group> listIterator(int index) {
return groups.listIterator(index);
}
@NotNull
public List<Group> subList(int fromIndex, int toIndex) {
return groups.subList(fromIndex, toIndex);
}
public Spliterator<Group> spliterator() {
return groups.spliterator();
}
public boolean removeIf(Predicate<? super Group> filter) {
return groups.removeIf(filter);
}
public Stream<Group> stream() {
return groups.stream();
}
public Stream<Group> parallelStream() {
return groups.parallelStream();
}
public void forEach(Consumer<? super Group> action) {
groups.forEach(action);
}
public void addListener(InvalidationListener listener) {
groups.addListener(listener);
}
public void removeListener(InvalidationListener listener) {
groups.removeListener(listener);
}
}
......@@ -5,25 +5,26 @@ import javafx.scene.control.Label;
import java.util.Comparator;
public class GroupsList extends ExtendedList<String> {
public class GroupsList extends ExtendedList<Group> {
@Override
public void initialize() {
super.initialize();
title.setText("Groups");
addField.setPromptText("New Group...");
}
@Override
Comparator<String> comparator() {
return Comparator.naturalOrder();
Comparator<Group> comparator() {
return Comparator.comparing(g -> g.name);
}
@Override
String[] provideItem(String... text) {
return text;
Group[] provideItem(String... text) {
return Utils.transform(text, Group::new, Group[]::new);
}
@Override
Node provideNode(String item) {
return new Label(item);
Node provideNode(Group item) {
return new Label(item.name);
}
}
package com.unitedworldminers.permio.editor;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.SplitPane;
import org.jetbrains.annotations.Nullable;
import org.yaml.snakeyaml.DumperOptions;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.representer.Representer;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.layout.Region;
import javafx.scene.layout.VBox;
public class GroupsScreen {
@FXML private MenuBar menuBar;
@FXML private SplitPane content;
@FXML private GroupsList groups;
@FXML private ComboBox<Group> inheritance;
@FXML private TextField prefix;
@FXML private TextField suffix;
@FXML private GroupsList groupsList;
@FXML private PermissionList permissions;
@FXML private PlayerList players;
private Path groupsFile;
private Path playersFile;
private Yaml yaml;
private Map<String, Map<String, Object>> groupdata = null;
private Map<String, Map<String, Object>> playerdata = null;
@FXML private VBox groupMeta;
@FXML
private void initialize() {
DumperOptions yamlOptions = new DumperOptions();
yamlOptions.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
yamlOptions.setAllowUnicode(true);
Representer yamlRepresenter = new Representer();
yamlRepresenter.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
yaml = new Yaml(yamlRepresenter, yamlOptions);
for (Menu m: menuBar.getMenus()) {
m.getItems().add(new MenuItem());
m.addEventHandler(Menu.ON_SHOWN, event -> {
m.hide();
m.fire();
});
}
// groupmeta width (combobox, spinner) enforcement
inheritance.prefWidthProperty().bind(((Region) inheritance.getParent()).widthProperty());
loadFromFile(Paths.get("groups.yml"), Paths.get("players.yml"));
// LISTENERS
groupsList.list.getSelectionModel().selectedItemProperty().addListener((obs, old, now) -> selectGroup(old, now));
}
@FXML
private void openFileDialog(ActionEvent actionEvent) {
}
@FXML
private void reload(ActionEvent actionEvent) {
reload();
}
public void loadFromFile(Path groupsFile, Path playersFile) {
Path gsave = this.groupsFile;
Path psave = this.playersFile;
this.groupsFile = groupsFile;
this.playersFile = playersFile;
if (reload() != null) {
this.groupsFile = gsave;
this.playersFile = psave;
}
}
@Nullable
private String reload() {
Map<String, Map<String, Object>> groupdata = loadYaml(groupsFile);
if (groupdata == null) return "Could not load groups from "+groupsFile.toString();
Map<String, Map<String, Object>> playerdata = loadYaml(playersFile);
if (playerdata == null) return "Could not load players from "+playersFile.toString();
this.groupdata = groupdata;
this.playerdata = playerdata;
groups.reset();
public void load() {
groupsList.reset();
permissions.reset();
players.reset();
groups.items.addAll(groupdata.keySet());
return null;
groupsList.setSource(MainScreen.groups);
}
@Nullable
private Map<String, Map<String,Object>> loadYaml(Path file) {
try (BufferedReader br = Files.newBufferedReader(file)) {
return yaml.loadAs(br, YamlType.class);
} catch (IOException e) {
return null;
private void selectGroup(Group old, Group now) {
setElementsDisabled(now == null);
if (now != null) {
permissions.setSource(now.permissions);
inheritance.setItems(MainScreen.groups.filtered(g -> !g.isChildOf(now)));
if (old != null) prefix.textProperty().unbindBidirectional(old.prefix);
prefix.textProperty().bindBidirectional(now.prefix);
if (old != null) suffix.textProperty().unbindBidirectional(old.suffix);
suffix.textProperty().bindBidirectional(now.suffix);
}
}
private abstract static class YamlType implements Map<String, Map<String, Object>> {
private void setElementsDisabled(boolean disabled) {
permissions.setDisable(disabled);
players.setDisable(disabled);
groupMeta.setDisable(disabled);
}
}
......@@ -14,7 +14,7 @@ public class Main extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("GroupsScreen.fxml"));
Parent root = FXMLLoader.load(getClass().getResource("MainScreen.fxml"));
primaryStage.setTitle("Permission Editor");
primaryStage.getIcons().add(new Image(getClass().getClassLoader().getResourceAsStream("com/unitedworldminers/permio/editor/img/PermIO.png")));
primaryStage.setScene(new Scene(root, 1000, 500));
......
package com.unitedworldminers.permio.editor;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import org.jetbrains.annotations.Nullable;
import java.nio.file.Path;
import java.nio.file.Paths;
public class MainScreen {
@FXML private Node groupsScreen;
@FXML private MenuBar menuBar;
public static GroupData groups = new GroupData();
public static PlayerData players = new PlayerData();
@FXML
private void initialize() {
// menubar direct item click hack
for (Menu m: menuBar.getMenus()) {
m.getItems().add(new MenuItem());
m.addEventHandler(Menu.ON_SHOWN, event -> {
m.hide();
m.fire();
});
}
// 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;
System.out.println(loaded ? "loaded" : "empty");
}
@FXML
private void menuOpen(ActionEvent actionEvent) {
}
@FXML
private void menuSave(ActionEvent actionEvent) {
System.out.println();
}
@FXML
private void menuReload(ActionEvent actionEvent) {
load(groups.location, players.location);
}
@Nullable
private String load(Path groupsFile, Path playersFile) {
try {
groups = new GroupData(groupsFile);
players = new PlayerData(playersFile, groups);
} catch (InstantiationException e) {
return e.getMessage();
}
((GroupsScreen) groupsScreen.getUserData()).load();
return null;
}
}
......@@ -17,6 +17,7 @@ public class PermissionList extends ExtendedList<String> {
public void initialize() {
super.initialize();
title.setText("Permissions");
addField.setPromptText("New Permission...");
}
@Override
......
package com.unitedworldminers.permio.editor;
import javafx.beans.property.*;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import java.util.List;
import java.util.Map;
public class Player {
private static final String KEY_PREFIX = "prefix";
private static final String KEY_SUFFIX = "suffix";
private static final String KEY_PERMISSIONS = "permissions";
private static final String KEY_GROUP = "group";
public final PlayerProfile identity;
public final StringProperty prefix = new SimpleStringProperty();
public final StringProperty suffix = new SimpleStringProperty();
public final ObservableList<String> permissions = FXCollections.observableArrayList();
public final ObjectProperty<Group> group = new SimpleObjectProperty<>();
@SuppressWarnings("unchecked")
public Player(PlayerProfile identity, Map<String, Object> raw, GroupData groupData) {
this(identity);
Object o = raw.get(KEY_PERMISSIONS);
if (o instanceof List) permissions.addAll((List<String>) o);
o = raw.get(KEY_GROUP);
if (o instanceof String) group.set(groupData.byName((String) o));
o = raw.get(KEY_PREFIX);
if (o instanceof String) prefix.set((String) o);
o = raw.get(KEY_SUFFIX);
if (o instanceof String) suffix.set((String) o);
}