Added ability to edit and prepare nicer views for shards.
This commit is contained in:
parent
f7df8a1eaf
commit
5ab1abbfff
|
@ -0,0 +1,107 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333333 4.2333333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="login_credentials_shard_node_icon.svg"
|
||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\login_credentials_shard_node_icon.png"
|
||||
inkscape:export-xdpi="192"
|
||||
inkscape:export-ydpi="192">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="89.600001"
|
||||
inkscape:cx="10.229603"
|
||||
inkscape:cy="7.4126105"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-292.76667)">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#72deff;fill-opacity:1;stroke:none;stroke-width:0.07803907;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="path817"
|
||||
sodipodi:sides="9"
|
||||
sodipodi:cx="2.1166666"
|
||||
sodipodi:cy="294.93815"
|
||||
sodipodi:r1="1.8178079"
|
||||
sodipodi:r2="1.2179312"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="0.87266463"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 3.6909344,295.84704 -0.7913968,0.0241 -0.1611441,0.77519 -0.6217269,-0.49025 -0.621727,0.49025 -0.1611441,-0.77519 -0.79139678,-0.0241 0.37483979,-0.69741 -0.59076328,-0.52715 0.73543197,-0.2933 -0.11370504,-0.78356 0.75190744,0.24804 0.416557,-0.67333 0.4165569,0.67333 0.7519075,-0.24804 -0.1137051,0.78356 0.735432,0.2933 -0.5907633,0.52715 z"
|
||||
inkscape:transform-center-x="0.06028767"
|
||||
inkscape:transform-center-y="0.030212626" />
|
||||
<g
|
||||
id="g828">
|
||||
<rect
|
||||
y="294.87439"
|
||||
x="1.5420023"
|
||||
height="0.95215333"
|
||||
width="1.1493286"
|
||||
id="rect816"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path818"
|
||||
d="m 1.8074821,294.89943 v -0.43431 c 0,0 -0.016704,-0.32365 0.3236467,-0.32365 0.340351,0 0.292326,0.29233 0.292326,0.29233 v 0.47816"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||
<rect
|
||||
y="295.05811"
|
||||
x="1.7157624"
|
||||
height="0.17957026"
|
||||
width="0.8018086"
|
||||
id="rect820"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.05291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="rect822"
|
||||
width="0.8018086"
|
||||
height="0.17957026"
|
||||
x="1.7157624"
|
||||
y="295.41309" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1,89 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 4.2333333 4.2333333"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||
sodipodi:docname="text_shard_node_icon.svg"
|
||||
inkscape:export-filename="A:\Programming\GitHub-andrewlalis\CrystalKeep\src\main\resources\nl\andrewlalis\crystalkeep\ui\images\text_shard_node_icon.png"
|
||||
inkscape:export-xdpi="192"
|
||||
inkscape:export-ydpi="192">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="44.8"
|
||||
inkscape:cx="8.2633984"
|
||||
inkscape:cy="6.8552682"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
units="px" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-292.76667)">
|
||||
<path
|
||||
sodipodi:type="star"
|
||||
style="fill:#72deff;fill-opacity:1;stroke:none;stroke-width:0.07803907;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:markers fill stroke"
|
||||
id="path817"
|
||||
sodipodi:sides="9"
|
||||
sodipodi:cx="2.1166666"
|
||||
sodipodi:cy="294.93815"
|
||||
sodipodi:r1="1.8178079"
|
||||
sodipodi:r2="1.2179312"
|
||||
sodipodi:arg1="0.52359878"
|
||||
sodipodi:arg2="0.87266463"
|
||||
inkscape:flatsided="false"
|
||||
inkscape:rounded="0"
|
||||
inkscape:randomized="0"
|
||||
d="m 3.6909344,295.84704 -0.7913968,0.0241 -0.1611441,0.77519 -0.6217269,-0.49025 -0.621727,0.49025 -0.1611441,-0.77519 -0.79139678,-0.0241 0.37483979,-0.69741 -0.59076328,-0.52715 0.73543197,-0.2933 -0.11370504,-0.78356 0.75190744,0.24804 0.416557,-0.67333 0.4165569,0.67333 0.7519075,-0.24804 -0.1137051,0.78356 0.735432,0.2933 -0.5907633,0.52715 z"
|
||||
inkscape:transform-center-x="0.06028767"
|
||||
inkscape:transform-center-y="0.030212626" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-weight:normal;font-size:1.9992249px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.12495156"
|
||||
x="1.4333378"
|
||||
y="295.61206"
|
||||
id="text818"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan816"
|
||||
x="1.4333378"
|
||||
y="295.61206"
|
||||
style="stroke-width:0.12495156">A</tspan></text>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.3 KiB |
|
@ -5,4 +5,5 @@ module crystalkeep {
|
|||
opens nl.andrewlalis.crystalkeep;
|
||||
|
||||
exports nl.andrewlalis.crystalkeep.control to javafx.fxml;
|
||||
exports nl.andrewlalis.crystalkeep.model to javafx.fxml;
|
||||
}
|
|
@ -29,7 +29,15 @@ public class CrystalKeep extends Application {
|
|||
stage.setScene(scene);
|
||||
stage.setTitle("CrystalKeep");
|
||||
stage.sizeToScene();
|
||||
model.setActiveCluster(this.loadRootCluster());
|
||||
|
||||
stage.show();
|
||||
|
||||
MainViewController controller = loader.getController();
|
||||
controller.init(model);
|
||||
}
|
||||
|
||||
private Cluster loadRootCluster() throws IOException {
|
||||
ClusterLoader clusterLoader = new ClusterLoader();
|
||||
Cluster rootCluster;
|
||||
try {
|
||||
|
@ -45,12 +53,6 @@ public class CrystalKeep extends Application {
|
|||
clusterLoader.saveDefault(rootCluster);
|
||||
System.out.println("Saved root cluster on first load.");
|
||||
}
|
||||
model.setActiveCluster(rootCluster);
|
||||
|
||||
stage.show();
|
||||
|
||||
MainViewController controller = loader.getController();
|
||||
controller.init(model);
|
||||
System.out.println(rootCluster);
|
||||
return rootCluster;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
package nl.andrewlalis.crystalkeep.control;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.TreeView;
|
||||
|
||||
public class ClusterTreeViewController {
|
||||
@FXML
|
||||
TreeView<String> clusterTreeView;
|
||||
}
|
|
@ -2,8 +2,6 @@ package nl.andrewlalis.crystalkeep.control;
|
|||
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.TreeItem;
|
||||
import javafx.scene.control.TreeView;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
@ -14,10 +12,21 @@ import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
|||
import nl.andrewlalis.crystalkeep.view.ClusterTreeItem;
|
||||
import nl.andrewlalis.crystalkeep.view.CrystalItemTreeCell;
|
||||
import nl.andrewlalis.crystalkeep.view.ShardTreeItem;
|
||||
import nl.andrewlalis.crystalkeep.view.shard_details.LoginCredentialsPane;
|
||||
import nl.andrewlalis.crystalkeep.view.shard_details.ShardPane;
|
||||
import nl.andrewlalis.crystalkeep.view.shard_details.TextShardPane;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class MainViewController implements ModelListener {
|
||||
private static final Map<Class<? extends Shard>, Class<? extends ShardPane<? extends Shard>>> shardPanesMap = new HashMap<>();
|
||||
static {
|
||||
shardPanesMap.put(TextShard.class, TextShardPane.class);
|
||||
shardPanesMap.put(LoginCredentialsShard.class, LoginCredentialsPane.class);
|
||||
}
|
||||
|
||||
private Model model;
|
||||
|
||||
@FXML
|
||||
|
@ -30,17 +39,17 @@ public class MainViewController implements ModelListener {
|
|||
this.model.addListener(this);
|
||||
this.activeClusterUpdated();
|
||||
assert(this.clusterTreeView != null);
|
||||
this.clusterTreeView.setCellFactory(param -> new CrystalItemTreeCell());
|
||||
this.clusterTreeView.setCellFactory(param -> new CrystalItemTreeCell(this.model));
|
||||
this.clusterTreeView.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shardDetailContainer.getChildren().clear();
|
||||
if (newValue instanceof ShardTreeItem) {
|
||||
var node = (ShardTreeItem) newValue;
|
||||
System.out.println(node.getShard());
|
||||
if (node.getShard() instanceof TextShard) {
|
||||
shardDetailContainer.getChildren().add(new TextArea(((TextShard) node.getShard()).getText()));
|
||||
} else if (node.getShard() instanceof LoginCredentialsShard) {
|
||||
shardDetailContainer.getChildren().add(new Label("Username: " + ((LoginCredentialsShard) node.getShard()).getUsername()));
|
||||
shardDetailContainer.getChildren().add(new Label("Password: " + ((LoginCredentialsShard) node.getShard()).getPassword()));
|
||||
var paneClass = shardPanesMap.get(node.getShard().getClass());
|
||||
try {
|
||||
var pane = paneClass.getDeclaredConstructor(node.getShard().getClass()).newInstance(node.getShard());
|
||||
shardDetailContainer.getChildren().add(pane);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -66,6 +75,7 @@ public class MainViewController implements ModelListener {
|
|||
|
||||
private TreeItem<CrystalItem> createNode(Cluster cluster) {
|
||||
ClusterTreeItem node = new ClusterTreeItem(cluster);
|
||||
node.setExpanded(true);
|
||||
for (Cluster child : cluster.getClustersOrdered()) {
|
||||
node.getChildren().add(this.createNode(child));
|
||||
}
|
||||
|
|
|
@ -38,10 +38,18 @@ public class Cluster implements Comparable<Cluster>, CrystalItem {
|
|||
this.shards.add(shard);
|
||||
}
|
||||
|
||||
public void removeShard(Shard shard) {
|
||||
this.shards.remove(shard);
|
||||
}
|
||||
|
||||
public void addCluster(Cluster cluster) {
|
||||
this.clusters.add(cluster);
|
||||
}
|
||||
|
||||
public void removeCluster(Cluster cluster) {
|
||||
this.clusters.remove(cluster);
|
||||
}
|
||||
|
||||
public List<Cluster> getClustersOrdered() {
|
||||
List<Cluster> clusters = new ArrayList<>(this.getClusters());
|
||||
clusters.sort(Comparator.naturalOrder());
|
||||
|
|
|
@ -19,6 +19,10 @@ public class Model {
|
|||
|
||||
public void setActiveCluster(Cluster activeCluster) {
|
||||
this.activeCluster = activeCluster;
|
||||
this.notifyListeners();
|
||||
}
|
||||
|
||||
public void notifyListeners() {
|
||||
this.listeners.forEach(ModelListener::activeClusterUpdated);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
package nl.andrewlalis.crystalkeep.model;
|
||||
|
||||
import nl.andrewlalis.crystalkeep.model.shards.ShardType;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A shard is a single "piece" of information, such as a snippet of text, login
|
||||
* credentials, an image, or a private key. All shards within a cluster should
|
||||
* have unique names.
|
||||
* credentials, an image, or a private key.
|
||||
* <p>
|
||||
* Due to the need to deserialize shards from byte arrays, it is required
|
||||
* that this parent class holds a type discriminator value, which is used to
|
||||
|
@ -55,7 +52,7 @@ public abstract class Shard implements Comparable<Shard>, CrystalItem {
|
|||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Shard shard = (Shard) o;
|
||||
return getName().equals(shard.getName()) && getType() == shard.getType();
|
||||
return getName().equals(shard.getName()) && getType() == shard.getType() && getCreatedAt().equals(shard.getCreatedAt());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package nl.andrewlalis.crystalkeep.model.shards;
|
||||
package nl.andrewlalis.crystalkeep.model;
|
||||
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
||||
|
||||
/**
|
||||
* Represents a distinct type of shard, and should correspond to exactly one
|
|
@ -3,7 +3,7 @@ package nl.andrewlalis.crystalkeep.model.serialization;
|
|||
import nl.andrewlalis.crystalkeep.model.Cluster;
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.ShardType;
|
||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -12,7 +12,6 @@ import java.io.OutputStream;
|
|||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package nl.andrewlalis.crystalkeep.model.shards;
|
||||
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||
import nl.andrewlalis.crystalkeep.model.serialization.ByteUtils;
|
||||
import nl.andrewlalis.crystalkeep.model.serialization.ShardSerializer;
|
||||
|
||||
|
@ -39,6 +40,11 @@ public class LoginCredentialsShard extends Shard {
|
|||
return super.toString() + ", username=\"" + this.username + "\", password=\"" + this.password + "\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIconPath() {
|
||||
return "/nl/andrewlalis/crystalkeep/ui/images/login_credentials_shard_node_icon.png";
|
||||
}
|
||||
|
||||
public static class Serializer implements ShardSerializer<LoginCredentialsShard> {
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package nl.andrewlalis.crystalkeep.model.shards;
|
||||
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
import nl.andrewlalis.crystalkeep.model.ShardType;
|
||||
import nl.andrewlalis.crystalkeep.model.serialization.ByteUtils;
|
||||
import nl.andrewlalis.crystalkeep.model.serialization.ShardSerializer;
|
||||
|
||||
|
@ -29,6 +30,11 @@ public class TextShard extends Shard {
|
|||
return super.toString() + ", text=\"" + this.text + "\"";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIconPath() {
|
||||
return "/nl/andrewlalis/crystalkeep/ui/images/text_shard_node_icon.png";
|
||||
}
|
||||
|
||||
public static class Serializer implements ShardSerializer<TextShard> {
|
||||
@Override
|
||||
public byte[] serialize(TextShard shard) throws IOException {
|
||||
|
|
|
@ -5,35 +5,54 @@ import javafx.scene.control.MenuItem;
|
|||
import javafx.scene.control.TreeCell;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import nl.andrewlalis.crystalkeep.model.Cluster;
|
||||
import nl.andrewlalis.crystalkeep.model.CrystalItem;
|
||||
import nl.andrewlalis.crystalkeep.model.Model;
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
public class CrystalItemTreeCell extends TreeCell<CrystalItem> {
|
||||
private final ContextMenu contextMenu;
|
||||
private final Model model;
|
||||
|
||||
public CrystalItemTreeCell() {
|
||||
MenuItem item = new MenuItem("Delete");
|
||||
this.contextMenu = new ContextMenu(item);
|
||||
public CrystalItemTreeCell(Model model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void updateItem(CrystalItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (!empty) {
|
||||
ContextMenu menu = new ContextMenu();
|
||||
if (item instanceof Cluster) {
|
||||
var addShardItem = new MenuItem("Add Shard");
|
||||
var addClusterItem = new MenuItem("Add Cluster");
|
||||
menu.getItems().addAll(addShardItem, addClusterItem);
|
||||
}
|
||||
var deleteItem = new MenuItem("Delete");
|
||||
deleteItem.setOnAction(event -> {
|
||||
if (this.getTreeItem().getParent() != null && this.getTreeItem().getParent() instanceof ClusterTreeItem) {
|
||||
var cluster = ((ClusterTreeItem) this.getTreeItem().getParent()).getCluster();
|
||||
if (item instanceof Shard) {
|
||||
cluster.removeShard((Shard) item);
|
||||
} else if (item instanceof Cluster) {
|
||||
cluster.removeCluster((Cluster) item);
|
||||
}
|
||||
this.model.notifyListeners();
|
||||
}
|
||||
});
|
||||
menu.getItems().add(deleteItem);
|
||||
this.setText(item.getName());
|
||||
InputStream is = getClass().getResourceAsStream(item.getIconPath());
|
||||
if (is != null) {
|
||||
ImageView icon = new ImageView(new Image(is));
|
||||
icon.setFitHeight(16);
|
||||
icon.setFitHeight(24);
|
||||
icon.setPreserveRatio(true);
|
||||
this.setGraphic(icon);
|
||||
}
|
||||
if (item instanceof Shard) {
|
||||
this.setContextMenu(this.contextMenu);
|
||||
}
|
||||
this.setContextMenu(menu);
|
||||
} else {
|
||||
this.setText(null);
|
||||
this.setGraphic(null);
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.CheckBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.PasswordField;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.Pane;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.LoginCredentialsShard;
|
||||
|
||||
public class LoginCredentialsPane extends ShardPane<LoginCredentialsShard> {
|
||||
public LoginCredentialsPane(LoginCredentialsShard shard) {
|
||||
super(shard);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getContent(LoginCredentialsShard shard) {
|
||||
GridPane gp = new GridPane();
|
||||
gp.setPadding(new Insets(5));
|
||||
gp.setHgap(5);
|
||||
gp.setVgap(5);
|
||||
gp.add(new Label("Username"), 0, 0);
|
||||
var usernameField = new TextField(shard.getUsername());
|
||||
usernameField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shard.setUsername(newValue);
|
||||
});
|
||||
gp.add(usernameField, 1, 0);
|
||||
gp.add(new Label("Password"), 0, 1);
|
||||
var passwordField = new PasswordField();
|
||||
passwordField.setText(shard.getPassword());
|
||||
var rawPasswordField = new TextField(shard.getPassword());
|
||||
rawPasswordField.setVisible(false);
|
||||
passwordField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shard.setPassword(newValue);
|
||||
rawPasswordField.setText(newValue);
|
||||
});
|
||||
rawPasswordField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shard.setPassword(newValue);
|
||||
passwordField.setText(newValue);
|
||||
});
|
||||
var passwordsContainer = new Pane();
|
||||
passwordsContainer.getChildren().add(passwordField);
|
||||
passwordsContainer.getChildren().add(rawPasswordField);
|
||||
gp.add(passwordsContainer, 1, 1);
|
||||
var showPasswordCheckbox = new CheckBox("Show password");
|
||||
showPasswordCheckbox.setSelected(false);
|
||||
showPasswordCheckbox.selectedProperty().addListener((observable, oldValue, newValue) -> {
|
||||
passwordField.setVisible(!newValue);
|
||||
rawPasswordField.setVisible(newValue);
|
||||
});
|
||||
gp.add(showPasswordCheckbox, 1, 2);
|
||||
return gp;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
import javafx.geometry.Orientation;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Separator;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
import nl.andrewlalis.crystalkeep.model.Shard;
|
||||
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public abstract class ShardPane<T extends Shard> extends VBox {
|
||||
public ShardPane(T shard) {
|
||||
this.setSpacing(5);
|
||||
GridPane gp = new GridPane();
|
||||
gp.setPadding(new Insets(5));
|
||||
gp.setHgap(5);
|
||||
gp.setVgap(5);
|
||||
gp.add(new Label("Name"), 0, 0);
|
||||
var nameField = new TextField(shard.getName());
|
||||
nameField.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shard.setName(newValue);
|
||||
});
|
||||
gp.add(nameField, 1, 0);
|
||||
gp.add(new Label("Created at"), 0, 1);
|
||||
var createdAtField = new TextField(shard.getCreatedAt().format(DateTimeFormatter.ofPattern("dd MMMM yyyy HH:mm:ss")));
|
||||
createdAtField.setEditable(false);
|
||||
gp.add(createdAtField, 1, 1);
|
||||
this.getChildren().add(gp);
|
||||
this.getChildren().add(new Separator(Orientation.HORIZONTAL));
|
||||
this.getChildren().add(this.getContent(shard));
|
||||
}
|
||||
|
||||
protected abstract Node getContent(T shard);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package nl.andrewlalis.crystalkeep.view.shard_details;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.TextArea;
|
||||
import nl.andrewlalis.crystalkeep.model.shards.TextShard;
|
||||
|
||||
public class TextShardPane extends ShardPane<TextShard> {
|
||||
public TextShardPane(TextShard shard) {
|
||||
super(shard);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getContent(TextShard shard) {
|
||||
var textArea = new TextArea(shard.getText());
|
||||
textArea.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
shard.setText(newValue);
|
||||
});
|
||||
return textArea;
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TreeView?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
|
||||
<BorderPane xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="nl.andrewlalis.crystalkeep.control.ClusterTreeViewController"
|
||||
prefWidth="200.0"
|
||||
>
|
||||
<top>
|
||||
<Label text="Clusters" BorderPane.alignment="TOP_CENTER"/>
|
||||
</top>
|
||||
<center>
|
||||
<TreeView fx:id="clusterTreeView" prefWidth="200.0"/>
|
||||
</center>
|
||||
</BorderPane>
|
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Loading…
Reference in New Issue