Skip to content
This repository was archived by the owner on Jan 9, 2024. It is now read-only.

Commit 6c565a1

Browse files
committed
release version 0.0.2
1 parent 69c8125 commit 6c565a1

File tree

9 files changed

+239
-16
lines changed

9 files changed

+239
-16
lines changed

README.md

+17-3
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,34 @@ java -jar PrettyZoo.jar
1919

2020
- [x] support dynamic update view
2121

22-
- [x] support update node data
23-
2422
- [ ] different nodes by style
2523

26-
- [ ] support CRD node
24+
- [x] support `CRUD` node
2725

2826
- [ ] remember history server and auto suggestion
2927

3028
- [ ] support ACL
3129

30+
- [ ] error log
31+
32+
- [ ] optmize user experience
33+
3234
## Example
3335

36+
### connect zookeeper
37+
3438
![](release/example/connectView.jpg)
3539

40+
### show node tree
41+
3642
![](release/example/mainView.jpg)
3743

44+
### delete node
45+
46+
![](release/example/deleteLeafNode.jpg)
47+
48+
### add node
49+
50+
![](release/example/addNode-01.jpg)
3851

52+
![](release/example/addNode-02.jpg)

build.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group 'cc.c1234'
8-
version '0.0.1-SNAPSHOT'
8+
version '0.0.2'
99

1010
sourceCompatibility = 1.8
1111

Binary file not shown.

release/example/addNode-01.jpg

38.8 KB
Loading

release/example/addNode-02.jpg

17.9 KB
Loading

release/example/deleteLeafNode.jpg

39.8 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package cc.cc1234.main.controller;
2+
3+
import javafx.application.Platform;
4+
import javafx.fxml.FXML;
5+
import javafx.fxml.FXMLLoader;
6+
import javafx.scene.Scene;
7+
import javafx.scene.control.CheckBox;
8+
import javafx.scene.control.Label;
9+
import javafx.scene.control.TextArea;
10+
import javafx.scene.control.TextField;
11+
import javafx.scene.layout.AnchorPane;
12+
import javafx.stage.Stage;
13+
import org.apache.curator.framework.CuratorFramework;
14+
import org.apache.zookeeper.CreateMode;
15+
16+
import java.io.IOException;
17+
18+
public class AddNodeViewController {
19+
20+
@FXML
21+
private TextField nodeNameTextField;
22+
23+
@FXML
24+
private TextArea nodeDataTextArea;
25+
26+
@FXML
27+
private CheckBox isNodeSeq;
28+
29+
@FXML
30+
private CheckBox isNodeEph;
31+
32+
@FXML
33+
private Label parentPathLabel;
34+
35+
private CuratorFramework curatorFramework;
36+
37+
private Stage stage;
38+
39+
public static void initController(String parentPath, CuratorFramework curatorFramework) throws IOException {
40+
String fxml = "AddNodeView.fxml";
41+
final FXMLLoader loader = new FXMLLoader();
42+
loader.setLocation(AddNodeViewController.class.getResource(fxml));
43+
AnchorPane panel = loader.load();
44+
final AddNodeViewController controller = loader.getController();
45+
controller.setCuratorFramework(curatorFramework);
46+
controller.setParentPath(parentPath);
47+
48+
final Scene scene = new Scene(panel);
49+
final Stage stage = new Stage();
50+
stage.setScene(scene);
51+
controller.setStage(stage);
52+
stage.showAndWait();
53+
}
54+
55+
public void setParentPath(String parentPath) {
56+
this.parentPathLabel.setText(parentPath);
57+
}
58+
59+
public void setStage(Stage stage) {
60+
this.stage = stage;
61+
}
62+
63+
public void setCuratorFramework(CuratorFramework curatorFramework) {
64+
this.curatorFramework = curatorFramework;
65+
}
66+
67+
@FXML
68+
private void onNodeAddAction() {
69+
final String nodeName = nodeNameTextField.getText();
70+
final String nodeData = nodeDataTextArea.getText();
71+
try {
72+
String path = parentPathLabel.getText() + "/" + nodeName;
73+
curatorFramework.create()
74+
.withMode(createMode())
75+
// must use Platform to close stage
76+
.inBackground(((client, event) -> Platform.runLater(() -> stage.close())))
77+
.forPath(path, nodeData.getBytes());
78+
} catch (Exception e) {
79+
throw new IllegalStateException(e);
80+
}
81+
}
82+
83+
private CreateMode createMode() {
84+
if (isNodeSeq.isSelected() && isNodeEph.isSelected()) {
85+
return CreateMode.EPHEMERAL_SEQUENTIAL;
86+
}
87+
88+
if (isNodeSeq.isSelected()) {
89+
return CreateMode.PERSISTENT_SEQUENTIAL;
90+
}
91+
92+
if (isNodeEph.isSelected()) {
93+
return CreateMode.EPHEMERAL;
94+
}
95+
96+
// TODO how to support CreateMode.CONTAINER ?
97+
return CreateMode.PERSISTENT;
98+
}
99+
}

src/main/java/cc/cc1234/main/controller/NodeTreeViewController.java

+99-12
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
1212
import org.apache.zookeeper.data.Stat;
1313

14+
import java.io.IOException;
1415
import java.util.Map;
1516
import java.util.concurrent.ConcurrentHashMap;
1617
import java.util.concurrent.atomic.AtomicInteger;
@@ -86,6 +87,7 @@ private void initialize() {
8687
initTreeItemListener();
8788
// create virtual root item
8889
initVirtualRoot("/");
90+
zkNodeTreeView.setCellFactory(view -> new TreeCellImpl());
8991
}
9092

9193
public void viewInit(CuratorFramework client) {
@@ -112,6 +114,8 @@ private void initTreeItemListener() {
112114
private void initVirtualRoot(String root) {
113115
final ZkNode zkNode = new ZkNode(root, root);
114116
TreeItem<ZkNode> virtualRoot = new TreeItem<>(zkNode);
117+
zkNode.setData("");
118+
zkNode.setStat(new Stat());
115119
treeItemMap.put(root, virtualRoot);
116120
zkNodeTreeView.setRoot(virtualRoot);
117121
}
@@ -194,18 +198,35 @@ private void onNodeAdded(CuratorFramework client, TreeCacheEvent event) {
194198
}
195199

196200
private void showStat(Stat stat) {
197-
this.ctimeLabel.setText(String.valueOf(stat.getCtime()));
198-
this.mtimeLabel.setText(String.valueOf(stat.getMtime()));
199-
200-
this.numChildrenLabel.setText(String.valueOf(stat.getNumChildren()));
201-
this.aclVersionLabel.setText(String.valueOf(stat.getAversion()));
202-
this.cversionLabel.setText(String.valueOf(stat.getCversion()));
203-
this.cZxidLabel.setText(String.valueOf(stat.getCzxid()));
204-
this.mZxidLabel.setText(String.valueOf(stat.getMzxid()));
205-
this.pZxidLabel.setText(String.valueOf(stat.getPzxid()));
206-
this.dataLengthLabel.setText(String.valueOf(stat.getDataLength()));
207-
this.dataVersionLabel.setText(String.valueOf(stat.getVersion()));
208-
this.ephemeralOwnerLabel.setText(String.valueOf(stat.getEphemeralOwner()));
201+
if (stat == null) {
202+
setDefaultValue();
203+
} else {
204+
this.ctimeLabel.setText(String.valueOf(stat.getCtime()));
205+
this.mtimeLabel.setText(String.valueOf(stat.getMtime()));
206+
this.numChildrenLabel.setText(String.valueOf(stat.getNumChildren()));
207+
this.aclVersionLabel.setText(String.valueOf(stat.getAversion()));
208+
this.cversionLabel.setText(String.valueOf(stat.getCversion()));
209+
this.cZxidLabel.setText(String.valueOf(stat.getCzxid()));
210+
this.mZxidLabel.setText(String.valueOf(stat.getMzxid()));
211+
this.pZxidLabel.setText(String.valueOf(stat.getPzxid()));
212+
this.dataLengthLabel.setText(String.valueOf(stat.getDataLength()));
213+
this.dataVersionLabel.setText(String.valueOf(stat.getVersion()));
214+
this.ephemeralOwnerLabel.setText(String.valueOf(stat.getEphemeralOwner()));
215+
}
216+
}
217+
218+
private void setDefaultValue() {
219+
this.ctimeLabel.setText("");
220+
this.mtimeLabel.setText("");
221+
this.numChildrenLabel.setText("");
222+
this.aclVersionLabel.setText("");
223+
this.cversionLabel.setText("");
224+
this.cZxidLabel.setText("");
225+
this.mZxidLabel.setText("");
226+
this.pZxidLabel.setText("");
227+
this.dataLengthLabel.setText("");
228+
this.dataVersionLabel.setText("");
229+
this.ephemeralOwnerLabel.setText("");
209230
}
210231

211232
private void showData(String data) {
@@ -220,4 +241,70 @@ private void updateDataAction() {
220241
throw new IllegalStateException(e);
221242
}
222243
}
244+
245+
final class TreeCellImpl extends TreeCell<ZkNode> {
246+
247+
private ContextMenu operationMenus;
248+
249+
private final MenuItem deleteMenu;
250+
251+
private final MenuItem addMenu;
252+
253+
254+
TreeCellImpl() {
255+
deleteMenu = new MenuItem("Delete");
256+
deleteMenu.setOnAction(event -> {
257+
try {
258+
curatorFramework.delete().forPath(getTreeItem().getValue().getPath());
259+
} catch (Exception e) {
260+
throw new IllegalStateException(e);
261+
}
262+
});
263+
264+
// TODO @vran add action
265+
addMenu = new MenuItem("Add");
266+
addMenu.setOnAction(event -> {
267+
try {
268+
AddNodeViewController.initController(getTreeItem().getValue().getPath(), curatorFramework);
269+
} catch (IOException e) {
270+
throw new IllegalStateException(e);
271+
}
272+
});
273+
operationMenus = new ContextMenu();
274+
}
275+
276+
@Override
277+
protected void updateItem(ZkNode item, boolean empty) {
278+
super.updateItem(item, empty);
279+
if (empty || item == null) {
280+
setText(null);
281+
setGraphic(null);
282+
} else {
283+
setText(item.getName());
284+
final TreeItem<ZkNode> treeItem = getTreeItem();
285+
setGraphic(treeItem.getGraphic());
286+
setContextMenu(operationMenus);
287+
288+
if (item.getStat() != null && item.getStat().getEphemeralOwner() == 0) {
289+
addIfAbsent(addMenu);
290+
} else {
291+
operationMenus.getItems().remove(addMenu);
292+
}
293+
294+
// add delete menu for leaf node
295+
if (treeItem.isLeaf() && treeItem.getParent() != null) {
296+
addIfAbsent(deleteMenu);
297+
} else {
298+
operationMenus.getItems().remove(deleteMenu);
299+
}
300+
301+
}
302+
}
303+
304+
private void addIfAbsent(MenuItem menuItem) {
305+
if (!operationMenus.getItems().contains(menuItem)) {
306+
operationMenus.getItems().add(menuItem);
307+
}
308+
}
309+
}
223310
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import javafx.scene.paint.*?>
4+
<?import javafx.scene.text.*?>
5+
<?import javafx.geometry.*?>
6+
<?import java.lang.*?>
7+
<?import java.util.*?>
8+
<?import javafx.scene.*?>
9+
<?import javafx.scene.control.*?>
10+
<?import javafx.scene.layout.*?>
11+
12+
13+
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="cc.cc1234.main.controller.AddNodeViewController">
14+
<children>
15+
<TextField fx:id="nodeNameTextField" layoutX="170.0" layoutY="53.0" prefHeight="27.0" prefWidth="251.0" promptText="input node name here" AnchorPane.leftAnchor="170.0" AnchorPane.rightAnchor="170.0" AnchorPane.topAnchor="53.0" />
16+
<CheckBox fx:id="isNodeSeq" layoutX="170.0" layoutY="99.0" mnemonicParsing="false" text="Sequence" AnchorPane.leftAnchor="170.0" />
17+
<CheckBox fx:id="isNodeEph" layoutX="335.0" layoutY="99.0" mnemonicParsing="false" text="Ephemeral" AnchorPane.rightAnchor="170.0" />
18+
<TextArea fx:id="nodeDataTextArea" layoutX="170.0" layoutY="144.0" prefHeight="200.0" prefWidth="260.0" promptText="Input node data here" wrapText="true" AnchorPane.leftAnchor="170.0" AnchorPane.rightAnchor="170.0" AnchorPane.topAnchor="144.0" />
19+
<Button contentDisplay="CENTER" layoutX="255.0" layoutY="352.0" mnemonicParsing="false" onAction="#onNodeAddAction" text="Add" AnchorPane.leftAnchor="250.0" AnchorPane.rightAnchor="250.0" />
20+
<Label fx:id="parentPathLabel" contentDisplay="CENTER" graphicTextGap="5.0" layoutX="224.0" layoutY="14.0" prefHeight="17.0" prefWidth="205.0" textFill="#f0371a" />
21+
<Label layoutX="161.0" layoutY="14.0" text="Parent" AnchorPane.leftAnchor="170.0" />
22+
</children>
23+
</AnchorPane>

0 commit comments

Comments
 (0)