gui - initial icon edit support
This commit is contained in:
parent
c25003c693
commit
670ed96167
9 changed files with 263 additions and 23 deletions
|
@ -76,6 +76,7 @@ public class Controller implements Initializable {
|
|||
private HooksDialog hooksDialog = new HooksDialog(this);
|
||||
private MobilityDialog mobilityDialog = new MobilityDialog(this);
|
||||
private ChartDialog chartDialog = new ChartDialog(this);
|
||||
private NodeTypesDialog nodeTypesDialog = new NodeTypesDialog(this);
|
||||
|
||||
public Controller() {
|
||||
// load configuration
|
||||
|
@ -139,6 +140,12 @@ public class Controller implements Initializable {
|
|||
nodeEmaneDialog.setOwner(window);
|
||||
configDialog.setOwner(window);
|
||||
mobilityDialog.setOwner(window);
|
||||
nodeTypesDialog.setOwner(window);
|
||||
}
|
||||
|
||||
@FXML
|
||||
private void onOptionsMenuNodeTypes(ActionEvent event) {
|
||||
nodeTypesDialog.showDialog();
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
|
|
@ -42,13 +42,22 @@ public class CoreNode {
|
|||
this.loaded = false;
|
||||
}
|
||||
|
||||
public LayeredIcon getGraphIcon() {
|
||||
if (graphIcon == null) {
|
||||
graphIcon = IconUtils.getIcon(icon);
|
||||
graphIcon.add(radioIcon);
|
||||
}
|
||||
// public void setExternalIcon(String iconPath) {
|
||||
// icon = iconPath;
|
||||
// graphIcon = IconUtils.getExternalLayeredIcon(icon);
|
||||
// graphIcon.add(radioIcon);
|
||||
// }
|
||||
|
||||
return graphIcon;
|
||||
public void setNodeType(NodeType nodeType) {
|
||||
type = nodeType.getValue();
|
||||
model = nodeType.getModel();
|
||||
icon = nodeType.getIcon();
|
||||
if (icon.startsWith("file:")) {
|
||||
graphIcon = IconUtils.getExternalLayeredIcon(icon);
|
||||
} else {
|
||||
graphIcon = IconUtils.getLayeredIcon(icon);
|
||||
}
|
||||
graphIcon.add(radioIcon);
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
|
|
|
@ -19,9 +19,9 @@ public class NodeType {
|
|||
private static final Map<String, NodeType> LOOKUP = new HashMap<>();
|
||||
private static final Map<Integer, String> DISPLAY_MAP = new HashMap<>();
|
||||
private final int value;
|
||||
private final String display;
|
||||
private final String model;
|
||||
private final String icon;
|
||||
private String display;
|
||||
private String model;
|
||||
private String icon;
|
||||
|
||||
// PHYSICAL = 1
|
||||
// RJ45 = 7
|
||||
|
|
|
@ -305,9 +305,7 @@ public class NetworkGraph {
|
|||
private void handleVertexAdded(GraphEvent.Vertex<CoreNode, CoreLink> vertexEvent) {
|
||||
CoreNode node = vertexEvent.getVertex();
|
||||
if (!node.isLoaded()) {
|
||||
node.setType(nodeType.getValue());
|
||||
node.setModel(nodeType.getModel());
|
||||
node.setIcon(nodeType.getIcon());
|
||||
node.setNodeType(nodeType);
|
||||
if (node.getType() == NodeType.EMANE) {
|
||||
String emaneModel = controller.getNodeEmaneDialog().getModels().get(0);
|
||||
node.setEmane(emaneModel);
|
||||
|
|
|
@ -62,7 +62,8 @@ public class GraphToolbar extends VBox {
|
|||
private SVGGlyph stopIcon;
|
||||
private JFXListView<Label> nodesList = new JFXListView<>();
|
||||
private JFXListView<Label> devicesList = new JFXListView<>();
|
||||
private Map<Label, NodeType> labelMap = new HashMap<>();
|
||||
private Map<String, NodeType> nodeTypeMap = new HashMap<>();
|
||||
private Map<String, Label> labelMap = new HashMap<>();
|
||||
private JFXButton selectedEditButton;
|
||||
private NodeType selectedNodeType;
|
||||
private boolean isEditing = false;
|
||||
|
@ -149,7 +150,8 @@ public class GraphToolbar extends VBox {
|
|||
icon.setFitWidth(NODES_ICON_SIZE);
|
||||
icon.setFitHeight(NODES_ICON_SIZE);
|
||||
Label label = new Label(nodeType.getDisplay(), icon);
|
||||
labelMap.put(label, nodeType);
|
||||
nodeTypeMap.put(nodeType.getDisplay(), nodeType);
|
||||
labelMap.put(nodeType.getDisplay(), label);
|
||||
|
||||
if (nodeType.getValue() == NodeType.DEFAULT) {
|
||||
nodesList.getItems().add(label);
|
||||
|
@ -165,7 +167,7 @@ public class GraphToolbar extends VBox {
|
|||
// initial node
|
||||
nodesList.getSelectionModel().selectFirst();
|
||||
Label selectedNodeLabel = nodesList.getSelectionModel().getSelectedItem();
|
||||
selectedNodeType = labelMap.get(selectedNodeLabel);
|
||||
selectedNodeType = nodeTypeMap.get(selectedNodeLabel.getText());
|
||||
selectedEditButton = nodesButton;
|
||||
controller.getNetworkGraph().setNodeType(selectedNodeType);
|
||||
updateButtonValues(nodesButton, selectedNodeLabel);
|
||||
|
@ -198,7 +200,7 @@ public class GraphToolbar extends VBox {
|
|||
}
|
||||
|
||||
updateButtonValues(nodesButton, current);
|
||||
selectedNodeType = labelMap.get(current);
|
||||
selectedNodeType = nodeTypeMap.get(current.getText());
|
||||
setSelectedEditButton(nodesButton);
|
||||
devicesList.getSelectionModel().clearSelection();
|
||||
controller.getNetworkGraph().setNodeType(selectedNodeType);
|
||||
|
@ -218,7 +220,7 @@ public class GraphToolbar extends VBox {
|
|||
}
|
||||
|
||||
updateButtonValues(devicesButton, current);
|
||||
selectedNodeType = labelMap.get(current);
|
||||
selectedNodeType = nodeTypeMap.get(current.getText());
|
||||
controller.getNetworkGraph().setNodeType(selectedNodeType);
|
||||
setSelectedEditButton(devicesButton);
|
||||
nodesList.getSelectionModel().clearSelection();
|
||||
|
@ -239,6 +241,18 @@ public class GraphToolbar extends VBox {
|
|||
}
|
||||
}
|
||||
|
||||
public void updateNodeType(String display, String uri) {
|
||||
Label label = labelMap.get(display);
|
||||
ImageView icon = new ImageView(uri);
|
||||
icon.setFitWidth(NODES_ICON_SIZE);
|
||||
icon.setFitHeight(NODES_ICON_SIZE);
|
||||
label.setGraphic(icon);
|
||||
|
||||
if (selectedNodeType.getDisplay().equals(display)) {
|
||||
updateButtonValues(nodesButton, label);
|
||||
}
|
||||
}
|
||||
|
||||
private void setSelected(boolean isSelected, JFXButton... others) {
|
||||
Arrays.stream(others)
|
||||
.forEach(x -> x.pseudoClassStateChanged(SELECTED_CLASS, isSelected));
|
||||
|
|
114
corefx/src/main/java/com/core/ui/NodeTypesDialog.java
Normal file
114
corefx/src/main/java/com/core/ui/NodeTypesDialog.java
Normal file
|
@ -0,0 +1,114 @@
|
|||
package com.core.ui;
|
||||
|
||||
import com.core.Controller;
|
||||
import com.core.data.CoreNode;
|
||||
import com.core.data.NodeType;
|
||||
import com.jfoenix.controls.JFXButton;
|
||||
import com.jfoenix.controls.JFXListView;
|
||||
import com.jfoenix.controls.JFXTextField;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.stage.FileChooser;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class NodeTypesDialog extends StageDialog {
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
|
||||
private final Map<String, NodeType> nodeTypeMap = new HashMap<>();
|
||||
private NodeType selectedNodeType;
|
||||
|
||||
@FXML
|
||||
private JFXListView<String> listView;
|
||||
|
||||
@FXML
|
||||
private JFXTextField modelTextField;
|
||||
|
||||
@FXML
|
||||
private JFXTextField displayTextField;
|
||||
|
||||
@FXML
|
||||
private JFXTextField iconTextField;
|
||||
|
||||
@FXML
|
||||
private JFXButton iconButton;
|
||||
|
||||
@FXML
|
||||
private ImageView iconImage;
|
||||
|
||||
@FXML
|
||||
private JFXButton saveButton;
|
||||
|
||||
@FXML
|
||||
private JFXButton addButton;
|
||||
|
||||
@FXML
|
||||
private JFXButton deleteButton;
|
||||
|
||||
public NodeTypesDialog(Controller controller) {
|
||||
super(controller, "/fxml/node_types_dialog.fxml");
|
||||
setTitle("Node Configuration");
|
||||
addCancelButton();
|
||||
|
||||
listView.getSelectionModel().selectedItemProperty().addListener((ov, prev, current) -> {
|
||||
if (current == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeType nodeType = nodeTypeMap.get(current);
|
||||
modelTextField.setText(nodeType.getModel());
|
||||
displayTextField.setText(nodeType.getDisplay());
|
||||
iconTextField.setText(nodeType.getIcon());
|
||||
iconImage.setImage(new Image(nodeType.getIcon()));
|
||||
selectedNodeType = nodeType;
|
||||
});
|
||||
|
||||
iconButton.setOnAction(event -> {
|
||||
FileChooser fileChooser = new FileChooser();
|
||||
fileChooser.setTitle("Select Icon");
|
||||
fileChooser.setInitialDirectory(new File(System.getProperty("user.home")));
|
||||
fileChooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("PNG", "*.png"));
|
||||
File file = fileChooser.showOpenDialog(controller.getWindow());
|
||||
if (file != null) {
|
||||
String uri = file.toURI().toString();
|
||||
iconImage.setImage(new Image(uri));
|
||||
iconTextField.setText(uri);
|
||||
}
|
||||
});
|
||||
|
||||
saveButton.setOnAction(event -> {
|
||||
String iconPath = iconTextField.getText();
|
||||
selectedNodeType.setIcon(iconPath);
|
||||
for (CoreNode node : controller.getNetworkGraph().getGraph().getVertices()) {
|
||||
if (!selectedNodeType.getKey().equals(node.getNodeTypeKey())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
node.setNodeType(selectedNodeType);
|
||||
}
|
||||
controller.getNetworkGraph().getGraphViewer().repaint();
|
||||
controller.getGraphToolbar().updateNodeType(selectedNodeType.getDisplay(), iconPath);
|
||||
Toast.info(String.format("Node %s Updated", selectedNodeType.getDisplay()));
|
||||
});
|
||||
}
|
||||
|
||||
public void showDialog() {
|
||||
listView.getItems().clear();
|
||||
nodeTypeMap.clear();
|
||||
for (NodeType nodeType : NodeType.getNodeTypes()) {
|
||||
if (nodeType.getValue() != NodeType.DEFAULT) {
|
||||
continue;
|
||||
}
|
||||
nodeTypeMap.put(nodeType.getDisplay(), nodeType);
|
||||
listView.getItems().add(nodeType.getDisplay());
|
||||
}
|
||||
listView.getSelectionModel().selectFirst();
|
||||
|
||||
show();
|
||||
}
|
||||
}
|
|
@ -9,24 +9,39 @@ import org.apache.logging.log4j.Logger;
|
|||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class IconUtils {
|
||||
private static final Logger logger = LogManager.getLogger();
|
||||
public static final int ICON_SIZE = 75;
|
||||
private static final Map<String, LayeredIcon> ICON_MAP = new HashMap<>();
|
||||
private static final Map<String, ImageIcon> ICON_MAP = new HashMap<>();
|
||||
|
||||
private IconUtils() {
|
||||
|
||||
}
|
||||
|
||||
public static LayeredIcon getIcon(String iconPath) {
|
||||
return ICON_MAP.computeIfAbsent(iconPath, key -> {
|
||||
ImageIcon imageIcon = new ImageIcon(IconUtils.class.getResource(iconPath));
|
||||
public static LayeredIcon getExternalLayeredIcon(String iconPath) {
|
||||
ImageIcon imageIcon = ICON_MAP.computeIfAbsent(iconPath, key -> {
|
||||
try {
|
||||
return new ImageIcon(Paths.get(new URI(iconPath)).toString());
|
||||
} catch (URISyntaxException ex) {
|
||||
logger.error("error loading icon: {}", iconPath);
|
||||
throw new IllegalArgumentException("invalid icon uri: " + iconPath);
|
||||
}
|
||||
});
|
||||
Image image = imageIcon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_DEFAULT);
|
||||
return new LayeredIcon(image);
|
||||
}
|
||||
|
||||
public static LayeredIcon getLayeredIcon(String iconPath) {
|
||||
ImageIcon imageIcon = ICON_MAP.computeIfAbsent(iconPath, key ->
|
||||
new ImageIcon(IconUtils.class.getResource(iconPath)));
|
||||
Image image = imageIcon.getImage().getScaledInstance(ICON_SIZE, ICON_SIZE, Image.SCALE_DEFAULT);
|
||||
return new LayeredIcon(image);
|
||||
});
|
||||
}
|
||||
|
||||
public static SVGGlyph get(String name) {
|
||||
|
|
|
@ -29,6 +29,11 @@
|
|||
<MenuItem mnemonicParsing="false" onAction="#onSessionHooksMenu" text="Hooks" />
|
||||
<MenuItem mnemonicParsing="false" onAction="#onSessionOptionsMenu" text="Options" />
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="Options">
|
||||
<items>
|
||||
<MenuItem mnemonicParsing="false" onAction="#onOptionsMenuNodeTypes" text="Node Configuration" />
|
||||
</items>
|
||||
</Menu>
|
||||
<Menu mnemonicParsing="false" text="Help">
|
||||
<items>
|
||||
|
|
78
corefx/src/main/resources/fxml/node_types_dialog.fxml
Normal file
78
corefx/src/main/resources/fxml/node_types_dialog.fxml
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import com.jfoenix.controls.JFXButton?>
|
||||
<?import com.jfoenix.controls.JFXListView?>
|
||||
<?import com.jfoenix.controls.JFXTextField?>
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.image.ImageView?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
|
||||
<GridPane hgap="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" vgap="10.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.171">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="33.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0">
|
||||
<children>
|
||||
<JFXListView fx:id="listView" VBox.vgrow="ALWAYS" />
|
||||
<GridPane hgap="10.0" vgap="10.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<JFXButton fx:id="addButton" maxWidth="1.7976931348623157E308" styleClass="core-button" text="Add" GridPane.rowIndex="1" />
|
||||
<JFXButton fx:id="deleteButton" maxWidth="1.7976931348623157E308" styleClass="core-button" text="Delete" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<JFXButton fx:id="saveButton" maxWidth="1.7976931348623157E308" styleClass="core-button" text="Save" GridPane.columnIndex="2" GridPane.rowIndex="1" />
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="10.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<Label maxWidth="1.7976931348623157E308" text="Model" />
|
||||
<JFXTextField fx:id="modelTextField" disable="true" />
|
||||
<Label maxWidth="1.7976931348623157E308" text="Display" />
|
||||
<JFXTextField fx:id="displayTextField" disable="true" />
|
||||
<Label maxWidth="1.7976931348623157E308" text="Icon" />
|
||||
<GridPane hgap="10.0" vgap="10.0">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" percentWidth="20.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<JFXTextField fx:id="iconTextField" disable="true" />
|
||||
<ImageView fx:id="iconImage" fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="2" GridPane.halignment="CENTER" />
|
||||
<JFXButton fx:id="iconButton" maxWidth="1.7976931348623157E308" styleClass="core-button" text="Find" GridPane.columnIndex="1" />
|
||||
</children>
|
||||
</GridPane>
|
||||
</children>
|
||||
<GridPane.margin>
|
||||
<Insets />
|
||||
</GridPane.margin>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
</children>
|
||||
</GridPane>
|
Loading…
Reference in a new issue